Define RenderFragment concept

This commit is contained in:
Steve Sanderson 2018-02-16 09:04:47 +00:00
parent 1ac5ee25c1
commit 29a6175ac1
9 changed files with 35 additions and 25 deletions

View File

@ -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);
}
}

View File

@ -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));
}
}
}

View File

@ -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);
}

View File

@ -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,

View File

@ -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));
}
}
}

View File

@ -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)

View File

@ -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"),

View File

@ -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

View File

@ -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();
}