Blazor 组件在 StateHasChanged() 之后未更新

Posted

技术标签:

【中文标题】Blazor 组件在 StateHasChanged() 之后未更新【英文标题】:Blazor Component not updating after StateHasChanged() 【发布时间】:2021-01-23 19:58:16 【问题描述】:

我有一个 Blazor 服务器端页面,其中包含以下内容:

@foreach (var s in OSTs)

    <div class="alert" style="height: 30px; background:@s.Color; color: @s.TextColor;">

        <div class="form-row">
            <div class="col-sm-3"><strong>@s.Stage</strong><br />@s.Description</div>
            <OpportunitiesStageDiv MyEditOst="@s" UpdateIt="AddOrEditStage"></OpportunitiesStageDiv>
            <div class="badge badge-primary" @onclick="() => MoveItUp(s)" style="cursor: pointer; width: 6rem;"><i class=" oi oi-arrow-top"></i> Move Up</div>
            <div class="badge badge-primary" @onclick="() => MoveItDown(s)" style="cursor: pointer; width: 6rem;"><i class="oi oi-arrow-bottom"></i> Move Down</div>
            <div class="badge badge-primary">@s.Id - @s.StageOrder</div>
        </div>
    </div>

组件 OpportunitiesStagesDiv 如下:

<div class="badge badge-primary" @onclick="() => EditStage(MyEditOst.Id)" style="cursor: pointer; width: 6rem;">Edit Stage</div>
<Modal @ref="@EditModal">
    <Title>Edit Opportunity Stage</Title>
    <Body>
        <EditOpportunityStage EditOSt="@MyEditOst" Complete="AddOrEditStage"></EditOpportunityStage>
    </Body>
    <Footer>
        <button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => EditModal.Close()">Close</button>
    </Footer>
</Modal>
@code 
    [Parameter]
    public OpportunityStagesTemplate MyEditOst  get; set; 
    private Modal EditModal = new Modal();
    [Parameter]
    public EventCallback<int> UpdateIt  get; set; 

    protected override void OnInitialized()
     
        base.OnInitialized();
    
    private void EditStage(int SId)
    
        EditModal.Open();
    
    private void AddOrEditStage(int Completed)
    
        if (Completed == 99)
        
        
        EditModal.Close();
    


MoveItUp(s) 和 MoveItDown(s) 是根据数据库查询中的 order 参数向上或向下移动 foreach 循环中的主 div 元素的函数。这完美地工作。奇怪的是,一旦一个DIV元素上移或下移,组件中的编辑功能@onclick="() =&gt; EditStage(MyEditOst.Id)"就会像上一个元素一样反映。

用于参考工作的 MoveItUp 和 MoveItDown 函数:

 private void MoveItUp(OpportunityStagesTemplate MyEditOst)
    
        if (MyEditOst.StageOrder > 1)
        
            OpportunitiesStagesTemplateGateway OSTGw = new OpportunitiesStagesTemplateGateway();
            OpportunityStagesTemplate PreviousOst = OSTGw.GetStageByOIdAndStageOrder(MyEditOst.OId, MyEditOst.StageOrder - 1);
            PreviousOst.StageOrder = MyEditOst.StageOrder;
            MyEditOst.StageOrder -= 1;
            OSTGw.UpdateOpportunityStage(PreviousOst);
            OSTGw.UpdateOpportunityStage(MyEditOst);
            ExecuteTheGetStages(LastId);
            StateHasChanged();
        
    
    private void MoveItDown(OpportunityStagesTemplate MyEditOst)
    
        OpportunitiesStagesTemplateGateway OSTGw = new OpportunitiesStagesTemplateGateway();
        int ct = OSTGw.GetCountByOId(MyEditOst.OId);
        if (ct > MyEditOst.StageOrder)
        
            OpportunityStagesTemplate NextOst = OSTGw.GetStageByOIdAndStageOrder(MyEditOst.OId, MyEditOst.StageOrder + 1);
            NextOst.StageOrder = MyEditOst.StageOrder;
            MyEditOst.StageOrder += 1;
            OSTGw.UpdateOpportunityStage(NextOst);
            OSTGw.UpdateOpportunityStage(MyEditOst);
            ExecuteTheGetStages(LastId);
            StateHasChanged();
        
    

例如我有一个列表如下:

<div 1 edit moveup movedown>
<div 2 edit moveup movedown>
<div 3 edit moveup movedown>

当我向上移动一个 div 时

<div 1 edit moveup movedown>
<div 3 edit moveup movedown>
<div 2 edit moveup movedown>

然后在第 2 行的 div 3 上单击编辑,它会像 div 2 一样显示编辑。似乎组件仍然保留在渲染 UI 上的位置,就好像 DIV 2 处于打开状态一样第二行和 DIV 3 仍在第三行,尽管上移和下移功能已更新数据库并正确更新 UI 以在列表移动时按顺序显示列表。有什么建议吗?

下面是示例渲染页面:

Sample list picture

【问题讨论】:

【参考方案1】:

在仔细阅读Microsoft LifeCycle 文档后,我找到了一个简单的解决方案。我发现如果使用:

protected override void OnParametersSet()

    ...

我的模态框上的编辑表单显示正确的信息。 OnParameterSet 允许我更新任何局部组件变量,即使在 OnInitialized() 上提供它们的原始参数已设置。

谢谢,我希望这个答案对大家有所帮助。

【讨论】:

以上是关于Blazor 组件在 StateHasChanged() 之后未更新的主要内容,如果未能解决你的问题,请参考以下文章

使用 Blazor 开发内部后台:了解 Blazor 组件

在 Blazor 组件中获取当前用户

在 blazor 应用程序之外使用 blazor 组件(例如,knockoutjs)

将 Blazor 组件渲染到现有 div(Blazor 无权访问)

Blazor 页面组件

为啥“InvokeAsync”在 Blazor 组件中显示为错误?