Blazor:StateHasChanged 可以在 parent 中调用,或者如果在 Child 中调用会有更好的性能?

Blazor: StateHasChanged could be called in parent or if called in Child has better performance?

我的问题是关于 StateHasChanged:

我在 Parent 中有此代码:

    [Inject]
    private IProjectActionsService ProjectActionsService { get; set; }
    private ProjectModel Project { get; set; }
    
    protected override void OnInitialized()        
    {                                 
        ProjectActionsService.FavouritesOnChange += FavouriteTasksChanged;

        await GetProjectData(Project);
    }

    private void FavouriteTasksChanged(TreeItemModel treeItem)
    {
        var remove = treeItem.Hidden;

        Project.TreeDataDict.TryGetValue(treeItem.NodeId, out treeItem);

        if (remove)
        {
            Project.TreeDataSource[0].Children.Remove(treeItem);
        }
        else
        {
            Project.TreeDataSource[0].Children.Add(treeItem);
        }

        StateHasChanged();
    }

这会重新呈现 child 向用户显示收藏夹

这里是Child:

    [Parameter]
    public ProjectModel Project { get; set; }

我的问题是,如果不是在 Parent 中调用 StateHasChanged,我可以对 child 执行以下操作:

    [Parameter]
    public ProjectModel Project { get; set; }

    protected override void OnInitialized()        
    {                                 
        ProjectActionsService.FavouritesOnChange += FavouriteTasksChanged;
    }

    private void FavouriteTasksChanged(TreeItemModel treeItem)
    {
        var remove = treeItem.Hidden;

        Project.TreeDataDict.TryGetValue(treeItem.NodeId, out treeItem);

        if (remove)
        {
            Project.TreeDataSource[0].Children.Remove(treeItem);
        }
        else
        {
            Project.TreeDataSource[0].Children.Add(treeItem);
        }

        StateHasChanged();
    }

并在 child 上调用 StatesHasChanged。

这会对性能有任何影响吗(例如:不进行 parent 重新渲染)或将做完全相同的事情(例如:只渲染显示给用户的位置,这只发生在 child) ??

更新从这里开始:

所以我做了一些测试,事实上在 Parent 中使用 StatHasChanged 会调用每个 child 组件的 OnAfterRender。通过 运行 在 child 它只运行自己的 OnAfterRender。

此致

Will this have any impact on performance (ex: not making parent rerender)

是的。为必要的最小范围调用 StateHasChanged。
假设树在子组件中呈现。

what I have read tells me that only the changed properties will be rendered

这是正确的,但首先 'diffing engine' 必须 运行,需要时间。而且该引擎在安全方面犯了错误:将重新渲染任何具有可变对象作为参数的组件。

来自Blazor performance page

  1. After a new set of parameter values is received, each component decides whether to rerender. By default, components rerender if the parameter values may have changed, for example, if they're mutable objects.

附带说明一下,ProjectActionsService 的生命周期(范围)是多少?我认为你最好有 @implement IDisposable 并用它来取消订阅 (-=) 你的事件处理程序。

我会在上面的答案中添加一些更一般的信息。

  1. 使用服务来管理您的数据很好,使用事件来通知更改也是如此。任何需要了解其正在使用的数据发生变化的组件都会注册通知并对任何变化做出反应——通常是通过重新渲染。试图强制从父级重新渲染子级是不行的。

  2. 你应该只有一个版本的真相 - 在你的情况下 ProjectModel。从您的代码中不清楚 Project 是您数据服务中对 Project 的引用,还是您在 Project.TreeDataSource[0].Children.Remove(treeItem); 中操作的本地副本。确保您的数据和所有数据操作都在服务中,并且直接引用服务中的 Project 或对其的本地引用。 “关注点分离”的原则。

您没有向我们展示您的渲染代码,因此很难评论 StateHasChanged 在您更改 TreeDataSource 后调用时会重新渲染的内容。通常,当发生重新渲染时,只有更改会传达给浏览器 window。但是,从显示的列表中删除元素可能会导致相当大的重新渲染。您可以使用@key 来帮助渲染器减轻负载。