为什么 Blazor 渲染组件两次
Why does Blazor renders component twice
我有一个简单的 Blazor 组件。
<div @onclick="HandleClick">Click me</div>
@code {
public async Task HandleClick()
{
await Task.Run(()=> System.Threading.Thread.Sleep(1000));
}
protected override void OnAfterRender(bool firstRender)
{
Console.WriteLine("Rendered");
}
}
当我单击 div 时,"Rendered" 被打印到控制台,并在 1 秒后再次打印,这意味着 blazor 已渲染组件两次。我知道 Blazor 会触发组件的自动重新呈现,作为向其分派事件的一部分。
但是为什么任务完成后会重新渲染呢?如何避免二次渲染?
我在 OnAfterRender 生命周期挂钩中有一些 JS 互操作,现在运行两次。我可以添加某种计数器,但这会污染我的代码,我想避免这种情况。
我的 HandleClick
是一个简单的 public void 方法然后一切正常,但这并不总是可能的
您可以像这样使用 firstRender 变量:
if(firstRender)
{
// Call JSInterop to initialize your js functions, etc.
// This code will execute only once in the component life cycle.
// The variable firstRender is true only after the first rendering of the
// component; that is, after the component has been created and initialized.
// Now, when you click the div element firstRender is false, but still the
// component is rendered twice, before the awaited method (Task.Run) is called,
// and after the awaited method completes. The first render occurs because UI
// event automatically invoke the StateHasChanged method. The second render
// occurs also automatically after an awaited method in an async method
// completes. This is how Blazor works, and it shouldn't bother you.
}
我遇到了同样的问题,但我的解决方案与@enet 提到的不同。
如果您通过循环显示组件(例如foreach 循环),您需要将@key 属性设置到组件上。在我的例子中,我有相同的组件,它当然接收具有不同唯一键的相同类型的对象,但 Blazor 无法区分这两者。因此,当两者之一的数据发生变化时,Blazor 会生成所有这些。
当您传递 @key="Your-unique-key" 时,Blazor 会监视该键而不是整个模型实例。
微软关于this的说明值得一读:
我有一个简单的 Blazor 组件。
<div @onclick="HandleClick">Click me</div>
@code {
public async Task HandleClick()
{
await Task.Run(()=> System.Threading.Thread.Sleep(1000));
}
protected override void OnAfterRender(bool firstRender)
{
Console.WriteLine("Rendered");
}
}
当我单击 div 时,"Rendered" 被打印到控制台,并在 1 秒后再次打印,这意味着 blazor 已渲染组件两次。我知道 Blazor 会触发组件的自动重新呈现,作为向其分派事件的一部分。
但是为什么任务完成后会重新渲染呢?如何避免二次渲染?
我在 OnAfterRender 生命周期挂钩中有一些 JS 互操作,现在运行两次。我可以添加某种计数器,但这会污染我的代码,我想避免这种情况。
我的 HandleClick
是一个简单的 public void 方法然后一切正常,但这并不总是可能的
您可以像这样使用 firstRender 变量:
if(firstRender)
{
// Call JSInterop to initialize your js functions, etc.
// This code will execute only once in the component life cycle.
// The variable firstRender is true only after the first rendering of the
// component; that is, after the component has been created and initialized.
// Now, when you click the div element firstRender is false, but still the
// component is rendered twice, before the awaited method (Task.Run) is called,
// and after the awaited method completes. The first render occurs because UI
// event automatically invoke the StateHasChanged method. The second render
// occurs also automatically after an awaited method in an async method
// completes. This is how Blazor works, and it shouldn't bother you.
}
我遇到了同样的问题,但我的解决方案与@enet 提到的不同。
如果您通过循环显示组件(例如foreach 循环),您需要将@key 属性设置到组件上。在我的例子中,我有相同的组件,它当然接收具有不同唯一键的相同类型的对象,但 Blazor 无法区分这两者。因此,当两者之一的数据发生变化时,Blazor 会生成所有这些。
当您传递 @key="Your-unique-key" 时,Blazor 会监视该键而不是整个模型实例。
微软关于this的说明值得一读: