Remove externally-callable Renderer.RenderInNewBatch() now that rendering is triggered by components themselves
This commit is contained in:
parent
804ab2d89f
commit
70a3ee3d98
|
|
@ -29,9 +29,6 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
|
|||
internal void DispatchBrowserEvent(int componentId, int eventHandlerId, UIEventArgs eventArgs)
|
||||
=> DispatchEvent(componentId, eventHandlerId, eventArgs);
|
||||
|
||||
internal void RenderNewBatchInternal(int componentId)
|
||||
=> RenderNewBatch(componentId);
|
||||
|
||||
/// <summary>
|
||||
/// Attaches a new root component to the renderer,
|
||||
/// causing it to be displayed in the specified DOM element.
|
||||
|
|
@ -59,7 +56,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
|
|||
_browserRendererId,
|
||||
domElementSelector,
|
||||
componentId);
|
||||
RenderNewBatch(componentId);
|
||||
component.SetParameters(ParameterCollection.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,14 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
|||
/// </summary>
|
||||
public readonly struct ParameterCollection
|
||||
{
|
||||
private static readonly RenderTreeFrame[] _emptyCollectionFrames = new RenderTreeFrame[]
|
||||
{
|
||||
RenderTreeFrame.Element(0, string.Empty).WithComponentSubtreeLength(1)
|
||||
};
|
||||
|
||||
private static readonly ParameterCollection _emptyCollection
|
||||
= new ParameterCollection(_emptyCollectionFrames, 0);
|
||||
|
||||
private readonly RenderTreeFrame[] _frames;
|
||||
private readonly int _ownerIndex;
|
||||
|
||||
|
|
@ -20,6 +28,11 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
|||
_ownerIndex = ownerIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an empty <see cref="ParameterCollection"/>.
|
||||
/// </summary>
|
||||
public static ParameterCollection Empty => _emptyCollection;
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through the <see cref="ParameterCollection"/>.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -64,52 +64,6 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
|||
/// <param name="renderBatch">The changes to the UI since the previous call.</param>
|
||||
protected abstract void UpdateDisplay(RenderBatch renderBatch);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the rendered state of the specified <see cref="IComponent"/>.
|
||||
/// </summary>
|
||||
/// <param name="componentId">The identifier of the <see cref="IComponent"/> to render.</param>
|
||||
protected void RenderNewBatch(int componentId)
|
||||
{
|
||||
// It's very important that components' rendering logic has no side-effects, and in particular
|
||||
// components must *not* trigger Render from inside their render logic, otherwise you could
|
||||
// easily get hard-to-debug infinite loops.
|
||||
// Since rendering is currently synchronous and single-threaded, we can enforce the above by
|
||||
// checking here that no other rendering process is already underway. This also means we only
|
||||
// need a single _renderBatchBuilder instance that can be reused throughout the lifetime of
|
||||
// the Renderer instance, which also means we're not allocating on a typical render cycle.
|
||||
// In the future, if rendering becomes async, we'll need a more sophisticated system of
|
||||
// capturing successive diffs from each component and probably serializing them for the
|
||||
// interop calls instead of using shared memory.
|
||||
|
||||
// Note that Monitor.TryEnter is not yet supported in Mono WASM, so using the following instead
|
||||
var renderAlreadyRunning = Interlocked.CompareExchange(ref _renderBatchLock, 1, 0) == 1;
|
||||
if (renderAlreadyRunning)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot render while a render is already in progress. " +
|
||||
"Render logic must not have side-effects such as manually triggering other rendering.");
|
||||
}
|
||||
|
||||
_sharedRenderBatchBuilder.ComponentRenderQueue.Enqueue(componentId);
|
||||
|
||||
try
|
||||
{
|
||||
// Process render queue until empty
|
||||
while (_sharedRenderBatchBuilder.ComponentRenderQueue.Count > 0)
|
||||
{
|
||||
var nextComponentIdToRender = _sharedRenderBatchBuilder.ComponentRenderQueue.Dequeue();
|
||||
RenderInExistingBatch(_sharedRenderBatchBuilder, nextComponentIdToRender);
|
||||
}
|
||||
|
||||
UpdateDisplay(_sharedRenderBatchBuilder.ToBatch());
|
||||
}
|
||||
finally
|
||||
{
|
||||
RemoveEventHandlerIds(_sharedRenderBatchBuilder.DisposedEventHandlerIds.ToRange());
|
||||
_sharedRenderBatchBuilder.Clear();
|
||||
Interlocked.Exchange(ref _renderBatchLock, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the specified component that an event has occurred.
|
||||
/// </summary>
|
||||
|
|
@ -171,6 +125,48 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
|||
? componentState
|
||||
: throw new ArgumentException($"The renderer does not have a component with ID {componentId}.");
|
||||
|
||||
private void RenderNewBatch(int componentId)
|
||||
{
|
||||
// It's very important that components' rendering logic has no side-effects, and in particular
|
||||
// components must *not* trigger Render from inside their render logic, otherwise you could
|
||||
// easily get hard-to-debug infinite loops.
|
||||
// Since rendering is currently synchronous and single-threaded, we can enforce the above by
|
||||
// checking here that no other rendering process is already underway. This also means we only
|
||||
// need a single _renderBatchBuilder instance that can be reused throughout the lifetime of
|
||||
// the Renderer instance, which also means we're not allocating on a typical render cycle.
|
||||
// In the future, if rendering becomes async, we'll need a more sophisticated system of
|
||||
// capturing successive diffs from each component and probably serializing them for the
|
||||
// interop calls instead of using shared memory.
|
||||
|
||||
// Note that Monitor.TryEnter is not yet supported in Mono WASM, so using the following instead
|
||||
var renderAlreadyRunning = Interlocked.CompareExchange(ref _renderBatchLock, 1, 0) == 1;
|
||||
if (renderAlreadyRunning)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot render while a render is already in progress. " +
|
||||
"Render logic must not have side-effects such as manually triggering other rendering.");
|
||||
}
|
||||
|
||||
_sharedRenderBatchBuilder.ComponentRenderQueue.Enqueue(componentId);
|
||||
|
||||
try
|
||||
{
|
||||
// Process render queue until empty
|
||||
while (_sharedRenderBatchBuilder.ComponentRenderQueue.Count > 0)
|
||||
{
|
||||
var nextComponentIdToRender = _sharedRenderBatchBuilder.ComponentRenderQueue.Dequeue();
|
||||
RenderInExistingBatch(_sharedRenderBatchBuilder, nextComponentIdToRender);
|
||||
}
|
||||
|
||||
UpdateDisplay(_sharedRenderBatchBuilder.ToBatch());
|
||||
}
|
||||
finally
|
||||
{
|
||||
RemoveEventHandlerIds(_sharedRenderBatchBuilder.DisposedEventHandlerIds.ToRange());
|
||||
_sharedRenderBatchBuilder.Clear();
|
||||
Interlocked.Exchange(ref _renderBatchLock, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderInExistingBatch(RenderBatchBuilder batchBuilder, int componentId)
|
||||
{
|
||||
GetRequiredComponentState(componentId).RenderIntoBatch(batchBuilder);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,10 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
public void SetParameters(ParameterCollection parameters)
|
||||
{
|
||||
parameters.AssignToProperties(this);
|
||||
_renderHandle.Render();
|
||||
TriggerRender();
|
||||
}
|
||||
|
||||
public void TriggerRender()
|
||||
=> _renderHandle.Render();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Act
|
||||
var componentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
|
||||
// Assert
|
||||
var batch = renderer.Batches.Single();
|
||||
|
|
@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Act/Assert
|
||||
var componentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
var batch = renderer.Batches.Single();
|
||||
var componentFrame = batch.ReferenceFrames
|
||||
.Single(frame => frame.FrameType == RenderTreeFrameType.Component);
|
||||
|
|
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
var componentId = renderer.AssignComponentId(component);
|
||||
|
||||
// Act/Assert: first render
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
var batch = renderer.Batches.Single();
|
||||
var firstDiff = batch.DiffsByComponentId[componentId].Single();
|
||||
Assert.Collection(firstDiff.Edits,
|
||||
|
|
@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Act/Assert: second render
|
||||
component.Message = "Modified message";
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
var secondBatch = renderer.Batches.Skip(1).Single();
|
||||
var secondDiff = secondBatch.DiffsByComponentId[componentId].Single();
|
||||
Assert.Collection(secondDiff.Edits,
|
||||
|
|
@ -127,7 +127,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
builder.CloseComponent();
|
||||
});
|
||||
var parentComponentId = renderer.AssignComponentId(parentComponent);
|
||||
renderer.RenderNewBatch(parentComponentId);
|
||||
parentComponent.TriggerRender();
|
||||
var nestedComponentFrame = renderer.Batches.Single()
|
||||
.ReferenceFrames
|
||||
.Single(frame => frame.FrameType == RenderTreeFrameType.Component);
|
||||
|
|
@ -136,7 +136,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Assert: inital render
|
||||
nestedComponent.Message = "Render 1";
|
||||
renderer.RenderNewBatch(nestedComponentId);
|
||||
nestedComponent.TriggerRender();
|
||||
var batch = renderer.Batches[1];
|
||||
var firstDiff = batch.DiffsByComponentId[nestedComponentId].Single();
|
||||
Assert.Collection(firstDiff.Edits,
|
||||
|
|
@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Act/Assert: re-render
|
||||
nestedComponent.Message = "Render 2";
|
||||
renderer.RenderNewBatch(nestedComponentId);
|
||||
nestedComponent.TriggerRender();
|
||||
var secondBatch = renderer.Batches[2];
|
||||
var secondDiff = secondBatch.DiffsByComponentId[nestedComponentId].Single();
|
||||
Assert.Collection(secondDiff.Edits,
|
||||
|
|
@ -173,7 +173,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
Handler = args => { receivedArgs = args; }
|
||||
};
|
||||
var componentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
|
||||
var eventHandlerId = renderer.Batches.Single()
|
||||
.ReferenceFrames
|
||||
|
|
@ -202,7 +202,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
builder.CloseComponent();
|
||||
});
|
||||
var parentComponentId = renderer.AssignComponentId(parentComponent);
|
||||
renderer.RenderNewBatch(parentComponentId);
|
||||
parentComponent.TriggerRender();
|
||||
|
||||
// Arrange: Render nested component
|
||||
var nestedComponentFrame = renderer.Batches.Single()
|
||||
|
|
@ -211,7 +211,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
var nestedComponent = (EventComponent)nestedComponentFrame.Component;
|
||||
nestedComponent.Handler = args => { receivedArgs = args; };
|
||||
var nestedComponentId = nestedComponentFrame.ComponentId;
|
||||
renderer.RenderNewBatch(nestedComponentId);
|
||||
nestedComponent.TriggerRender();
|
||||
|
||||
// Find nested component's event handler ID
|
||||
var eventHandlerId = renderer.Batches[1]
|
||||
|
|
@ -242,7 +242,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
});
|
||||
|
||||
var componentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
|
||||
var eventHandlerId = renderer.Batches.Single()
|
||||
.ReferenceFrames
|
||||
|
|
@ -259,19 +259,6 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
$"events because it does not implement {typeof(IHandleEvent).FullName}.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CannotRenderUnknownComponents()
|
||||
{
|
||||
// Arrange
|
||||
var renderer = new TestRenderer();
|
||||
|
||||
// Act/Assert
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
renderer.RenderNewBatch(123);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CannotDispatchEventsToUnknownComponents()
|
||||
{
|
||||
|
|
@ -291,19 +278,32 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
// Arrange
|
||||
var renderer1 = new TestRenderer();
|
||||
var renderer2 = new TestRenderer();
|
||||
var component = new MessageComponent { Message = "Hello, world!" };
|
||||
var component = new MultiRendererComponent();
|
||||
var renderer1ComponentId = renderer1.AssignComponentId(component);
|
||||
renderer2.AssignComponentId(new TestComponent(null)); // Just so they don't get the same IDs
|
||||
var renderer2ComponentId = renderer2.AssignComponentId(component);
|
||||
|
||||
// Act/Assert: Render component in renderer1
|
||||
renderer1.RenderNewBatch(renderer1ComponentId);
|
||||
Assert.True(renderer1.Batches.Single().DiffsByComponentId.ContainsKey(renderer1ComponentId));
|
||||
Assert.Empty(renderer2.Batches);
|
||||
// Act/Assert
|
||||
component.TriggerRender();
|
||||
var renderer1Batch = renderer1.Batches.Single();
|
||||
var renderer1Diff = renderer1Batch.DiffsByComponentId[renderer1ComponentId].Single();
|
||||
Assert.Collection(renderer1Diff.Edits,
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
AssertFrame.Text(renderer1Batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||
$"Hello from {nameof(MultiRendererComponent)}", 0);
|
||||
});
|
||||
|
||||
// Act/Assert: Render same component in renderer2
|
||||
renderer2.RenderNewBatch(renderer2ComponentId);
|
||||
Assert.True(renderer2.Batches.Single().DiffsByComponentId.ContainsKey(renderer2ComponentId));
|
||||
var renderer2Batch = renderer2.Batches.Single();
|
||||
var renderer2Diff = renderer2Batch.DiffsByComponentId[renderer2ComponentId].Single();
|
||||
Assert.Collection(renderer2Diff.Edits,
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
AssertFrame.Text(renderer2Batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||
$"Hello from {nameof(MultiRendererComponent)}", 0);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -320,7 +320,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
});
|
||||
|
||||
var rootComponentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(rootComponentId);
|
||||
component.TriggerRender();
|
||||
|
||||
var nestedComponentFrame = renderer.Batches.Single()
|
||||
.ReferenceFrames
|
||||
|
|
@ -329,7 +329,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Act: Second render
|
||||
message = "Modified message";
|
||||
renderer.RenderNewBatch(rootComponentId);
|
||||
component.TriggerRender();
|
||||
|
||||
// Assert
|
||||
var batch = renderer.Batches[1];
|
||||
|
|
@ -361,7 +361,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
});
|
||||
|
||||
var rootComponentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(rootComponentId);
|
||||
component.TriggerRender();
|
||||
|
||||
var originalComponentFrame = renderer.Batches.Single()
|
||||
.ReferenceFrames
|
||||
|
|
@ -375,7 +375,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Act: Second render
|
||||
firstRender = false;
|
||||
renderer.RenderNewBatch(rootComponentId);
|
||||
component.TriggerRender();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(256, childComponentInstance.IntProperty);
|
||||
|
|
@ -397,7 +397,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
});
|
||||
|
||||
var rootComponentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(rootComponentId);
|
||||
component.TriggerRender();
|
||||
|
||||
var childComponentId = renderer.Batches.Single()
|
||||
.ReferenceFrames
|
||||
|
|
@ -406,7 +406,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Act: Second render
|
||||
firstRender = false;
|
||||
renderer.RenderNewBatch(rootComponentId);
|
||||
component.TriggerRender();
|
||||
var diff = renderer.Batches[1].DiffsByComponentId[childComponentId].Single();
|
||||
|
||||
// Assert
|
||||
|
|
@ -441,7 +441,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
var rootComponentId = renderer.AssignComponentId(component);
|
||||
|
||||
// Act/Assert 1: First render, capturing child component IDs
|
||||
renderer.RenderNewBatch(rootComponentId);
|
||||
component.TriggerRender();
|
||||
var batch = renderer.Batches.Single();
|
||||
var rootComponentDiff = batch.DiffsByComponentId[rootComponentId].Single();
|
||||
var childComponentIds = rootComponentDiff
|
||||
|
|
@ -454,7 +454,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Act: Second render
|
||||
firstRender = false;
|
||||
renderer.RenderNewBatch(rootComponentId);
|
||||
component.TriggerRender();
|
||||
|
||||
// Assert: Applicable children are included in disposal list
|
||||
Assert.Equal(new[] { 1, 3 }, renderer.Batches[1].DisposedComponentIDs);
|
||||
|
|
@ -469,7 +469,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
UIEventHandler origEventHandler = args => { eventCount++; };
|
||||
var component = new EventComponent { Handler = origEventHandler };
|
||||
var componentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
var origEventHandlerId = renderer.Batches.Single()
|
||||
.ReferenceFrames
|
||||
.Where(f => f.FrameType == RenderTreeFrameType.Attribute)
|
||||
|
|
@ -484,7 +484,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
// Now change the attribute value
|
||||
var newEventCount = 0;
|
||||
component.Handler = args => { newEventCount++; };
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
|
||||
// Act/Assert 2: Can no longer fire the original event, but can fire the new event
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
|
|
@ -506,7 +506,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
UIEventHandler origEventHandler = args => { eventCount++; };
|
||||
var component = new EventComponent { Handler = origEventHandler };
|
||||
var componentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
var origEventHandlerId = renderer.Batches.Single()
|
||||
.ReferenceFrames
|
||||
.Where(f => f.FrameType == RenderTreeFrameType.Attribute)
|
||||
|
|
@ -520,7 +520,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Now remove the event attribute
|
||||
component.Handler = null;
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
|
||||
// Act/Assert 2: Can no longer fire the original event
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
|
|
@ -546,7 +546,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
}
|
||||
};
|
||||
var rootComponentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(rootComponentId);
|
||||
component.TriggerRender();
|
||||
var batch = renderer.Batches.Single();
|
||||
var rootComponentDiff = batch.DiffsByComponentId[rootComponentId].Single();
|
||||
var rootComponentFrame = batch.ReferenceFrames[0];
|
||||
|
|
@ -569,7 +569,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Now remove the EventComponent
|
||||
component.IncludeChild = false;
|
||||
renderer.RenderNewBatch(rootComponentId);
|
||||
component.TriggerRender();
|
||||
|
||||
// Act/Assert 2: Can no longer fire the original event
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
|
|
@ -588,7 +588,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
UIEventHandler origEventHandler = args => { eventCount++; };
|
||||
var component = new EventComponent { Handler = origEventHandler };
|
||||
var componentId = renderer.AssignComponentId(component);
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
var origEventHandlerId = renderer.Batches.Single()
|
||||
.ReferenceFrames
|
||||
.Where(f => f.FrameType == RenderTreeFrameType.Attribute)
|
||||
|
|
@ -602,7 +602,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
|
||||
// Now remove the ancestor element
|
||||
component.SkipElement = true;
|
||||
renderer.RenderNewBatch(componentId);
|
||||
component.TriggerRender();
|
||||
|
||||
// Act/Assert 2: Can no longer fire the original event
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
|
|
@ -675,7 +675,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
var parentComponentId = renderer.AssignComponentId(parent);
|
||||
|
||||
// Act
|
||||
renderer.RenderNewBatch(parentComponentId);
|
||||
parent.TriggerRender();
|
||||
|
||||
// Assert
|
||||
var batch = renderer.Batches.Single();
|
||||
|
|
@ -739,9 +739,6 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
public new int AssignComponentId(IComponent component)
|
||||
=> base.AssignComponentId(component);
|
||||
|
||||
public new void RenderNewBatch(int componentId)
|
||||
=> base.RenderNewBatch(componentId);
|
||||
|
||||
public new void DispatchEvent(int componentId, int eventHandlerId, UIEventArgs args)
|
||||
=> base.DispatchEvent(componentId, eventHandlerId, args);
|
||||
|
||||
|
|
@ -910,5 +907,29 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
builder.AddText(0, "Child is here");
|
||||
}
|
||||
}
|
||||
|
||||
private class MultiRendererComponent : IComponent
|
||||
{
|
||||
private readonly List<RenderHandle> _renderHandles
|
||||
= new List<RenderHandle>();
|
||||
|
||||
public void BuildRenderTree(RenderTreeBuilder builder)
|
||||
=> builder.AddText(0, $"Hello from {nameof(MultiRendererComponent)}");
|
||||
|
||||
public void Init(RenderHandle renderHandle)
|
||||
=> _renderHandles.Add(renderHandle);
|
||||
|
||||
public void SetParameters(ParameterCollection parameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void TriggerRender()
|
||||
{
|
||||
foreach (var renderHandle in _renderHandles)
|
||||
{
|
||||
renderHandle.Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue