【问题标题】:What exactly triggers a Blazor component to redraw itself?究竟是什么触发了 Blazor 组件重绘自身?
【发布时间】:2020-03-07 21:40:56
【问题描述】:

我有 Blazor WebAssembly 应用程序。我有一个共享模型类的父子组件。当子级更新模型上的值时,子级会重绘自己,但父级不会。那么究竟是什么触发了 Blazor 组件重绘自身?我找不到任何关于 Blazor 特定方面的文档。

我有一个 POCO 模型类。在实际应用中,这来自一个单独的程序集。模型/AwesomenessModel.cs:

namespace BlazorApp.Models {
    public class AwesomenessModel {
        public int? Level { get; set; }
    }
}

我的索引页面。 Pages/Index.razor:

@page "/"

@using BlazorApp.Components
@using BlazorApp.Models

<Awesomeness AwesomenessModel="@AwesomenessModel"></Awesomeness>

@code {
    private AwesomenessModel AwesomenessModel = new AwesomenessModel();
}

父类。我添加了一个重绘按钮来验证内容是否应该已更改。组件/Awesomeness.razor:

@using BlazorApp.Models

@if (AwesomenessModel.Level.HasValue) {
    <div>Awesomeness is @AwesomenessModel.Level.Value</div>
} else {
    for (int i = 0; i < 10; i++) {
        <AwesomenessSelector AwesomenessModel="@AwesomenessModel" Level="@i"></AwesomenessSelector>
    }
}
<div><button class="btn btn-link" @onclick="RedrawClick">Redraw</button></div>

@code {
    [Parameter]
    public AwesomenessModel AwesomenessModel { get; set; }

    private void RedrawClick() {
        this.StateHasChanged();
    }
}

对 Awesomeness 模型进行实际更改的子组件。组件/AwesomenessSelector.razor:

@using BlazorApp.Models

@if (!AwesomenessModel.Level.HasValue) {
    <div><button class="btn btn-link" @onclick="LevelClick">@Level</button></div>
}

@code {
    [Parameter]
    public AwesomenessModel AwesomenessModel { get; set; }

    [Parameter]
    public int Level { get; set; }

    private void LevelClick() {
        AwesomenessModel.Level = Level;
    }
}

当我运行应用程序并单击一个令人敬畏的级别时,该级别会消失(AwesomenessSelector 组件重新绘制),但其余部分仍然可见并且没有“Awesomeness is...”消息(Awesomeness 组件没有更新)。如果我然后单击“重绘”按钮强制重绘 Awesomeness 组件,我会收到正确的“Awesomeness is...”消息。

我可能没有以正确的方式构建代码以使父组件自动重绘。在这种情况下我应该如何构建它?

【问题讨论】:

    标签: asp.net-mvc blazor blazor-client-side


    【解决方案1】:

    子组件为 OnLevelClick 添加一个 EventCallback

    @using BlazorApp.Models
    
    @if (!AwesomenessModel.Level.HasValue) {
        <div><button class="btn btn-link" @onclick="LevelClick">@Level</button></div>
    }
    
    @code {
        [Parameter]
        public AwesomenessModel AwesomenessModel { get; set; }
    
        [Parameter]
        public int Level { get; set; }
    
        [Parameter]
        public EventCallback<string> OnLevelClick { get; set; }
    
        private void LevelClick() {
            AwesomenessModel.Level = Level;
            OnLevelClick.InvokeAsync();
        }
    }
    

    父组件为 OnLevelClick 添加 Handler

    @using BlazorApp.Models
    
    @if (AwesomenessModel.Level.HasValue) {
        <div>Awesomeness is @AwesomenessModel.Level.Value</div>
    } else {
        for (int i = 0; i < 10; i++) {
            <AwesomenessSelector AwesomenessModel="@AwesomenessModel" Level="@i" @OnLevelClick="OnLevelClick"></AwesomenessSelector>
        }
    }
    
    @code {
        [Parameter]
        public AwesomenessModel AwesomenessModel { get; set; }
    
        private void OnLevelClick() {
            this.StateHasChanged();
        }
    }
    

    希望对你有帮助

    【讨论】:

    • 这种模式肯定会触发父母正确地重新绘制自己,这就是我用来解决问题的方法 - 谢谢。我仍然有点好奇究竟孩子的自动重绘是如何工作的。
    • "OnLevelClick.InvokeAsync();"它在那里缺少一个论点
    【解决方案2】:

    您需要StateHasChanged() 在不知道子控件已更新的父控件上。我相信您应该在需要更新父级时触发的子级上创建一个事件。然后在触发事件时的父级StateHasChanged()。所有理论,但应该有效。

    【讨论】:

      猜你喜欢
      • 2018-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-15
      • 1970-01-01
      • 2021-10-14
      • 2010-12-29
      • 1970-01-01
      相关资源
      最近更新 更多