Define RenderFragment concept
This commit is contained in:
parent
1ac5ee25c1
commit
29a6175ac1
|
|
@ -20,14 +20,14 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
|||
{
|
||||
public const string BuildRenderTreeMethodName = nameof(BuildRenderTree);
|
||||
|
||||
private readonly Action<RenderTreeBuilder> _renderAction;
|
||||
private readonly RenderFragment _renderFragment;
|
||||
private RenderHandle _renderHandle;
|
||||
private bool _hasNeverRendered = true;
|
||||
private bool _hasPendingQueuedRender;
|
||||
|
||||
public BlazorComponent()
|
||||
{
|
||||
_renderAction = BuildRenderTree;
|
||||
_renderFragment = BuildRenderTree;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
|||
if (_hasNeverRendered || ShouldRender())
|
||||
{
|
||||
_hasPendingQueuedRender = true;
|
||||
_renderHandle.Render(_renderAction);
|
||||
_renderHandle.Render(_renderFragment);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,14 +31,15 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
|||
/// <summary>
|
||||
/// Notifies the renderer that the component should be rendered.
|
||||
/// </summary>
|
||||
public void Render(Action<RenderTreeBuilder> renderAction)
|
||||
/// <param name="renderFragment">The content that should be rendered.</param>
|
||||
public void Render(RenderFragment renderFragment)
|
||||
{
|
||||
if (_renderer == null)
|
||||
{
|
||||
throw new InvalidOperationException("The render handle is not yet assigned.");
|
||||
}
|
||||
|
||||
_renderer.AddToRenderQueue(new RenderQueueEntry(_componentId, renderAction));
|
||||
_renderer.AddToRenderQueue(new RenderQueueEntry(_componentId, renderFragment));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.RenderTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a segment of UI content, implemented as a delegate that
|
||||
/// writes the content to a <see cref="RenderTreeBuilder"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="RenderTreeBuilder"/> to which the content should be written.</param>
|
||||
public delegate void RenderFragment(RenderTreeBuilder builder);
|
||||
}
|
||||
|
|
@ -35,13 +35,13 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
|||
_renderTreeBuilderPrevious = new RenderTreeBuilder(renderer);
|
||||
}
|
||||
|
||||
public void RenderIntoBatch(RenderBatchBuilder batchBuilder, Action<RenderTreeBuilder> renderAction)
|
||||
public void RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)
|
||||
{
|
||||
// Swap the old and new tree builders
|
||||
(_renderTreeBuilderCurrent, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, _renderTreeBuilderCurrent);
|
||||
|
||||
_renderTreeBuilderCurrent.Clear();
|
||||
renderAction(_renderTreeBuilderCurrent);
|
||||
renderFragment(_renderTreeBuilderCurrent);
|
||||
|
||||
var diff = RenderTreeDiffBuilder.ComputeDiff(
|
||||
_renderer,
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
|||
internal readonly struct RenderQueueEntry
|
||||
{
|
||||
public readonly int ComponentId;
|
||||
public readonly Action<RenderTreeBuilder> RenderAction;
|
||||
public readonly RenderFragment RenderFragment;
|
||||
|
||||
public RenderQueueEntry(int componentId, Action<RenderTreeBuilder> renderAction)
|
||||
public RenderQueueEntry(int componentId, RenderFragment renderFragment)
|
||||
{
|
||||
ComponentId = componentId;
|
||||
RenderAction = renderAction ?? throw new ArgumentNullException(nameof(renderAction));
|
||||
RenderFragment = renderFragment ?? throw new ArgumentNullException(nameof(renderFragment));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
|||
{
|
||||
var componentId = renderQueueEntry.ComponentId;
|
||||
GetRequiredComponentState(componentId)
|
||||
.RenderIntoBatch(_batchBuilder, renderQueueEntry.RenderAction);
|
||||
.RenderIntoBatch(_batchBuilder, renderQueueEntry.RenderFragment);
|
||||
|
||||
// Process disposal queue now in case it causes further component renders to be enqueued
|
||||
while (_batchBuilder.ComponentDisposalQueue.Count > 0)
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecognizesEquivalentFramesAsSameCases))]
|
||||
public void RecognizesEquivalentFramesAsSame(Action<RenderTreeBuilder> appendAction)
|
||||
public void RecognizesEquivalentFramesAsSame(RenderFragment appendFragment)
|
||||
{
|
||||
// Arrange
|
||||
appendAction(oldTree);
|
||||
appendAction(newTree);
|
||||
appendFragment(oldTree);
|
||||
appendFragment(newTree);
|
||||
|
||||
// Act
|
||||
var (result, referenceFrames) = GetSingleUpdatedComponent(initializeFromFrames: true);
|
||||
|
|
@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
}
|
||||
|
||||
public static IEnumerable<object[]> RecognizesEquivalentFramesAsSameCases()
|
||||
=> new Action<RenderTreeBuilder>[]
|
||||
=> new RenderFragment[]
|
||||
{
|
||||
builder => builder.AddContent(0, "Hello"),
|
||||
builder => builder.OpenElement(0, "Some Element"),
|
||||
|
|
|
|||
|
|
@ -790,11 +790,11 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
private class TestComponent : IComponent
|
||||
{
|
||||
private RenderHandle _renderHandle;
|
||||
private Action<RenderTreeBuilder> _renderAction;
|
||||
private RenderFragment _renderFragment;
|
||||
|
||||
public TestComponent(Action<RenderTreeBuilder> renderAction)
|
||||
public TestComponent(RenderFragment renderFragment)
|
||||
{
|
||||
_renderAction = renderAction;
|
||||
_renderFragment = renderFragment;
|
||||
}
|
||||
|
||||
public void Init(RenderHandle renderHandle)
|
||||
|
|
@ -806,7 +806,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
=> TriggerRender();
|
||||
|
||||
public void TriggerRender()
|
||||
=> _renderHandle.Render(_renderAction);
|
||||
=> _renderHandle.Render(_renderFragment);
|
||||
}
|
||||
|
||||
private class MessageComponent : AutoRenderComponent
|
||||
|
|
|
|||
|
|
@ -12,16 +12,13 @@ namespace BasicTestApp
|
|||
private RenderHandle _renderHandle;
|
||||
private bool _showRegion;
|
||||
|
||||
// Important: Notice that the sequence numbers inside the region are higher
|
||||
// Important: Notice that the sequence numbers inside the fragment are higher
|
||||
// that the sequence numbers outside it. Without the region delimiter, the
|
||||
// differencer would think the following nodes had been removed, then the
|
||||
// region was inserted, followed by a new copy of the following nodes. That's
|
||||
// not as efficient and wouldn't preserve focus etc.
|
||||
private Action<RenderTreeBuilder> _exampleRegion = builder =>
|
||||
private RenderFragment _exampleContent = builder =>
|
||||
{
|
||||
// TODO: Support some kind of RenderBlock primitive
|
||||
// which is an Action<RenderTreeBuilder>. Can use the
|
||||
// same type name for RenderHandle.Render's arg.
|
||||
builder.OpenElement(100, "p");
|
||||
builder.AddAttribute(101, "name", "region-element");
|
||||
builder.AddAttribute(102, "style", "color: red");
|
||||
|
|
@ -52,7 +49,7 @@ namespace BasicTestApp
|
|||
if (_showRegion)
|
||||
{
|
||||
builder.OpenRegion(3);
|
||||
_exampleRegion(builder);
|
||||
_exampleContent(builder);
|
||||
builder.CloseRegion();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue