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);
|
public const string BuildRenderTreeMethodName = nameof(BuildRenderTree);
|
||||||
|
|
||||||
private readonly Action<RenderTreeBuilder> _renderAction;
|
private readonly RenderFragment _renderFragment;
|
||||||
private RenderHandle _renderHandle;
|
private RenderHandle _renderHandle;
|
||||||
private bool _hasNeverRendered = true;
|
private bool _hasNeverRendered = true;
|
||||||
private bool _hasPendingQueuedRender;
|
private bool _hasPendingQueuedRender;
|
||||||
|
|
||||||
public BlazorComponent()
|
public BlazorComponent()
|
||||||
{
|
{
|
||||||
_renderAction = BuildRenderTree;
|
_renderFragment = BuildRenderTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
||||||
if (_hasNeverRendered || ShouldRender())
|
if (_hasNeverRendered || ShouldRender())
|
||||||
{
|
{
|
||||||
_hasPendingQueuedRender = true;
|
_hasPendingQueuedRender = true;
|
||||||
_renderHandle.Render(_renderAction);
|
_renderHandle.Render(_renderFragment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,15 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Notifies the renderer that the component should be rendered.
|
/// Notifies the renderer that the component should be rendered.
|
||||||
/// </summary>
|
/// </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)
|
if (_renderer == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("The render handle is not yet assigned.");
|
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);
|
_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
|
// Swap the old and new tree builders
|
||||||
(_renderTreeBuilderCurrent, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, _renderTreeBuilderCurrent);
|
(_renderTreeBuilderCurrent, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, _renderTreeBuilderCurrent);
|
||||||
|
|
||||||
_renderTreeBuilderCurrent.Clear();
|
_renderTreeBuilderCurrent.Clear();
|
||||||
renderAction(_renderTreeBuilderCurrent);
|
renderFragment(_renderTreeBuilderCurrent);
|
||||||
|
|
||||||
var diff = RenderTreeDiffBuilder.ComputeDiff(
|
var diff = RenderTreeDiffBuilder.ComputeDiff(
|
||||||
_renderer,
|
_renderer,
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
internal readonly struct RenderQueueEntry
|
internal readonly struct RenderQueueEntry
|
||||||
{
|
{
|
||||||
public readonly int ComponentId;
|
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;
|
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;
|
var componentId = renderQueueEntry.ComponentId;
|
||||||
GetRequiredComponentState(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
|
// Process disposal queue now in case it causes further component renders to be enqueued
|
||||||
while (_batchBuilder.ComponentDisposalQueue.Count > 0)
|
while (_batchBuilder.ComponentDisposalQueue.Count > 0)
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,11 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(RecognizesEquivalentFramesAsSameCases))]
|
[MemberData(nameof(RecognizesEquivalentFramesAsSameCases))]
|
||||||
public void RecognizesEquivalentFramesAsSame(Action<RenderTreeBuilder> appendAction)
|
public void RecognizesEquivalentFramesAsSame(RenderFragment appendFragment)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
appendAction(oldTree);
|
appendFragment(oldTree);
|
||||||
appendAction(newTree);
|
appendFragment(newTree);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var (result, referenceFrames) = GetSingleUpdatedComponent(initializeFromFrames: true);
|
var (result, referenceFrames) = GetSingleUpdatedComponent(initializeFromFrames: true);
|
||||||
|
|
@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<object[]> RecognizesEquivalentFramesAsSameCases()
|
public static IEnumerable<object[]> RecognizesEquivalentFramesAsSameCases()
|
||||||
=> new Action<RenderTreeBuilder>[]
|
=> new RenderFragment[]
|
||||||
{
|
{
|
||||||
builder => builder.AddContent(0, "Hello"),
|
builder => builder.AddContent(0, "Hello"),
|
||||||
builder => builder.OpenElement(0, "Some Element"),
|
builder => builder.OpenElement(0, "Some Element"),
|
||||||
|
|
|
||||||
|
|
@ -790,11 +790,11 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
private class TestComponent : IComponent
|
private class TestComponent : IComponent
|
||||||
{
|
{
|
||||||
private RenderHandle _renderHandle;
|
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)
|
public void Init(RenderHandle renderHandle)
|
||||||
|
|
@ -806,7 +806,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
=> TriggerRender();
|
=> TriggerRender();
|
||||||
|
|
||||||
public void TriggerRender()
|
public void TriggerRender()
|
||||||
=> _renderHandle.Render(_renderAction);
|
=> _renderHandle.Render(_renderFragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MessageComponent : AutoRenderComponent
|
private class MessageComponent : AutoRenderComponent
|
||||||
|
|
|
||||||
|
|
@ -12,16 +12,13 @@ namespace BasicTestApp
|
||||||
private RenderHandle _renderHandle;
|
private RenderHandle _renderHandle;
|
||||||
private bool _showRegion;
|
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
|
// that the sequence numbers outside it. Without the region delimiter, the
|
||||||
// differencer would think the following nodes had been removed, then 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
|
// region was inserted, followed by a new copy of the following nodes. That's
|
||||||
// not as efficient and wouldn't preserve focus etc.
|
// 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.OpenElement(100, "p");
|
||||||
builder.AddAttribute(101, "name", "region-element");
|
builder.AddAttribute(101, "name", "region-element");
|
||||||
builder.AddAttribute(102, "style", "color: red");
|
builder.AddAttribute(102, "style", "color: red");
|
||||||
|
|
@ -52,7 +49,7 @@ namespace BasicTestApp
|
||||||
if (_showRegion)
|
if (_showRegion)
|
||||||
{
|
{
|
||||||
builder.OpenRegion(3);
|
builder.OpenRegion(3);
|
||||||
_exampleRegion(builder);
|
_exampleContent(builder);
|
||||||
builder.CloseRegion();
|
builder.CloseRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue