首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >blazor组件什么时候呈现?

blazor组件什么时候呈现?
EN

Stack Overflow用户
提问于 2022-07-20 02:38:59
回答 2查看 449关注 0票数 2

在下面来自此页的图表中,它显示了当调用OnInitializedAsync返回一个不完整的任务时,它将等待任务,然后呈现组件。

但是,返回不完整任务时实际发生的情况似乎是立即呈现组件,然后在不完整任务完成后再次呈现。

页面后面的一个例子似乎证实了这一点。如果组件没有在调用OnInitializedAsync之后立即呈现,而是在任务返回完成后第一次呈现,那么您将永远不会看到“加载.”。消息。

OnParametersSetAsync行为显示为相同。它在返回不完整的任务时立即呈现一次,然后在该任务完成后再呈现一次。

我是误解了呈现生命周期,还是文档中的错误?

谢谢

代码语言:javascript
代码运行次数:0
运行
复制
@page "/fetchdata"
@using BlazorSample.Data
@inject WeatherForecastService ForecastService

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from a service.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <!-- forecast data in table element content -->
    </table>
}

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-07-20 09:42:58

要完全回答您的问题,我们需要深入研究ComponentBase代码。

您的代码正在异步世界中运行,在这个世界中,代码块可以产生并将控制权还给调用者--您的“不完整任务被返回”。

当组件第一次呈现时,当任何参数发生更改时,渲染器都会调用SetParametersAsync

代码语言:javascript
代码运行次数:0
运行
复制
public virtual Task SetParametersAsync(ParameterView parameters)
{
    parameters.SetParameterProperties(this);
    if (!_initialized)
    {
        _initialized = true;
        return RunInitAndSetParametersAsync();
    }
    else
        return CallOnParametersSetAsync();
}

RunInitAndSetParametersAsync负责初始化。我留下了comments的评论,其中解释了StateHasChanged调用。

代码语言:javascript
代码运行次数:0
运行
复制
private async Task RunInitAndSetParametersAsync()
{
    OnInitialized();
    var task = OnInitializedAsync();

    if (task.Status != TaskStatus.RanToCompletion && task.Status != TaskStatus.Canceled)
    {
        // Call state has changed here so that we render after the sync part of OnInitAsync has run
        // and wait for it to finish before we continue. If no async work has been done yet, we want
        // to defer calling StateHasChanged up until the first bit of async code happens or until
        // the end. Additionally, we want to avoid calling StateHasChanged if no
        // async work is to be performed.
        StateHasChanged();
        try
        {
            await task;
        }
        catch // avoiding exception filters for AOT runtime support
        {
            if (!task.IsCanceled)
                throw;
        }
        // Don't call StateHasChanged here. CallOnParametersSetAsync should handle that for us.
    }
    await CallOnParametersSetAsync();
}

每次参数更改都会调用CallOnParametersSetAsync

代码语言:javascript
代码运行次数:0
运行
复制
private Task CallOnParametersSetAsync()
{
    OnParametersSet();
    var task = OnParametersSetAsync();
    // If no async work is to be performed, i.e. the task has already ran to completion
    // or was canceled by the time we got to inspect it, avoid going async and re-invoking
    // StateHasChanged at the culmination of the async work.
    var shouldAwaitTask = task.Status != TaskStatus.RanToCompletion &&
        task.Status != TaskStatus.Canceled;

    // We always call StateHasChanged here as we want to trigger a rerender after OnParametersSet and
    // the synchronous part of OnParametersSetAsync has run.
    StateHasChanged();

    return shouldAwaitTask ?
        CallStateHasChangedOnAsyncCompletion(task) :
        Task.CompletedTask;
}

在图中,在上面的代码中用“StateHasChanged”代替“呈现”。

该图表使用工作“呈现”,这有点误导。这意味着当实际发生的是呈现片段(构建组件UI标记的代码块)时,UI重新呈现在Renderer的呈现队列中。它应该说“请求呈现”或类似的东西。

如果触发呈现事件或调用StateHasChanged的组件代码都是同步代码,则渲染程序只在代码完成时获得线程时间。代码块需要为Renderer“屈服”,以便在进程中获得线程时间。

同样重要的是要理解,并不是所有基于任务的方法都能产生结果。许多代码只是任务包装器中的同步代码。

因此,如果OnInitializedAsyncOnParametersSetAsync中的代码产生一个呈现事件,则在第一个结果上,然后在完成时。

在同步代码块中“屈服”的一个常见做法是添加这一行代码,以使渲染器呈现。

代码语言:javascript
代码运行次数:0
运行
复制
await Task.Delay(1);

你可以在这里看到ComponentBase - https://github.com/dotnet/aspnetcore/blob/main/src/Components/Components/src/ComponentBase.cs

票数 3
EN

Stack Overflow用户

发布于 2022-07-20 05:49:49

短总结

  • Blazor在每个生命周期事件和UI事件之前和之后添加两个“免费”StateHasChanged调用。
  • StateHasChanged只请求html更新,而不执行更新。
  • 只有在事件发生后才能满足更新请求。 或者当主线程由await 释放时
    • 不是每个await都会释放线程。

因此,当您想确保屏幕得到更新时,请使用

代码语言:javascript
代码运行次数:0
运行
复制
StateHasChanged();
await Task.Delay(1);

旧答案

当返回不完整的任务时,它会立即呈现组件,然后在不完整的任务完成后再次呈现。

是的,这是一个可能的顺序。

流程图显示了显示组件的步骤。从图片中不太清楚的是,实际呈现不是这个流的一部分,它发生在同步上下文上。当您的代码await是某物时,可能会发生这种情况。

所以我们有一个非异步序列:

  • OninitialzedAsync
  • OnParametersSetAsync
  • 渲染
  • OnAfterRenderAsync

但是,当这个代码路径中有什么异步时,那么在await期间可以有一个额外的呈现。当您在此流中调用StateHasChanged时,可以进行更多的呈现。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73045404

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档