2

我是 blazor 的新手,仍在学习,我的仪表板有一个状态问题。

我有一个组件可以获取仪表板和面板:

@if (Data == null)
{
    <Loader></Loader>
    return;
}
<Row NoGutters="true">
    @foreach (var panel in Data.Panels)
    {
        <Column XS="12" SM="12" MD="6" LG="6" XL="4" Class="mb-4">
            <CascadingValue Value="@panel.Id">
                <DashboardMatare DateHeader="@panel.DateHeader" Header="@panel.Header" ></DashboardMatare>
            </CascadingValue>
        </Column>
    }
</Row>

它通过 OnParametersSetAsync 获取数据并且工作正常,它获取新面板并呈现它们

但是当我切换到另一个仪表板时,前一个仪表板的相同值仍然存在于“DashboardMatereChartJs”中。

如果仪表板之间的面板数量不同,它将呈现新面板。

我将 panelId 级联给孩子,这样 blazor 就会明白它需要更改状态。

仪表板材料:

<DashboardContainer>

<DashboardHeader Header="@Header" DateHeader="@DateHeader"></DashboardHeader>

<CascadingValue Value=PanelId>
    <DashboardMatareChartJs />
</CascadingValue>

DashboardMatereChartJs:

if (Data == null)
{
    <Loader />
    return;
}

<div class="pl-3">
    <Row NoGutters="true" Class="h-75">
        <Column Class="col-12">
            <div class="matare">
                <div class="valueWrapper">
                    <canvas class="meterGraph" ref="ReferenceToChartJs">
                    </canvas>
                </div>
            </div>
        </Column>
    </Row>
    <Row>
        <Column Class="text-left col-12">
            <DashboardJamforMed JamforMedText="Data.JamforMedText" IsProcent="Data.ShowPercentage"></DashboardJamforMed>
        </Column>
    </Row>
</div>


[Inject]
protected HttpClient HttpClient { get; set; }

[CascadingParameter]
public Guid PanelId { get; set; }

public ElementReference ReferenceToChartJs { get; set; }

[Inject]
private IJSRuntime JsRuntime { get; set; }

public DashboardPanelGraphDataDto Data { get; set; }

protected override async Task OnInitializedAsync()
{
    Data = await HttpClient.GetFromJsonAsync<DashboardPanelGraphDataDto>($"api/DashboardBlazor/GetChartData/{PanelId}");
}

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (Data == null || ReferenceToChartJs.Context == null)
    {
        return;
    }

    await JsRuntime.InvokeVoidAsync("chartService.drawGraph", ReferenceToChartJs, Data.ChartData, Data.TypeOfGraph, Data.ShowPercentage);
}

DashboardHeader 将始终具有正确的数据

问题似乎是当 PanelId 更改时组件不会调用 OnInitializedAsync 。我认为这是一个结构问题,因为我试图通过@ref 强制 statehaschanged 并从父级调用 StateHasChanged,但仍然不起作用。

如果我通过“DashboardMatareChartJs”上的 OnParametersSetAsync 获取数据,那么它将加载新数据,但它会多次加载它并且对于仍在视图中的面板。我知道这意味着我可能还没有 100% 了解 blazor 的生命周期,所以希望有人能把我推向正确的方向。

提前致谢!

4

1 回答 1

1

尝试使用 @key 指令属性强制 Blazor 重建 DashboardMatare 对象,如下所示:

<DashboardMatare @key="@panel.Id" DateHeader="@panel.DateHeader" Header="@panel.Header" ></DashboardMatare>

这个答案基于以下几点:

您还可以使用 @key 防止 Blazor 在对象更改时保留元素或组件子树:

<div @key="currentPerson">
    ... content that depends on currentPerson ...
</div>

如果 @currentPerson 发生更改,@key 属性指令会强制 Blazor 丢弃整个及其后代,并使用新元素和组件在 UI 中重建子树。如果您需要保证 @currentPerson 更改时不保留任何 UI 状态,这将很有用。

链接到源...

于 2020-10-28T12:16:36.640 回答