Blazor:更改边界 属性 不会更新视图

Blazor: Changing bound property does not update the view

我在 Blazor(服务器端)中有一个带有 InputText 控件的 EditForm。表单绑定到模型 class,InputText 字段绑定到由本地存储支持的单个 属性。

页面加载时,InputText 显示空白值。我调用 InitAsync 方法从本地存储异步加载数据。这有效,但是使用加载的数据设置 属性 不会更新视图。

如果我将值绑定到具有单向绑定的 span 标记而不是 InputText(具有双向绑定),则会出现同样的问题。

从存储中异步加载数据后如何让视图更新?

View/component class:

@inject Blazored.LocalStorage.ILocalStorageService localStorage
<EditForm Model="@model" class="pl-4 pr-3 py-1 loginform" OnValidSubmit="@HandleValidSubmit">
    <span>model.OperID</span>    
    <InputText class="form-control mr-sm-2" style="width: 158px" placeholder="OperID"  @bind-Value="@model.OperID"></InputText>
    <button class="btn btn-success oi oi-account-login" @onclick="Login"></button>
</EditForm>


@code {   
    private Models.MainModel model = new Models.MainModel();


    protected override async Task OnAfterRenderAsync(bool firstRender)
    {       
        await model.InitializeAsync(localStorage);
    }


    void Login()
    {

    }


    private void HandleValidSubmit()
    {
        Console.WriteLine("OnValidSubmit");
    }
}

型号class:

public class MainModel
{
    Blazored.LocalStorage.ILocalStorageService? localStorage;

    public MainModel()
    {

    }


    public async Task InitializeAsync(Blazored.LocalStorage.ILocalStorageService localStorage)
    {
        this.localStorage = localStorage;

        if (localStorage != null)
        {
            // the value loads correctly, but setting the property does not cause the view to update as it should. 
            // ConfigureAwait(false) makes no difference...
            OperID = await localStorage.GetItemAsync<string?>("OperID").ConfigureAwait(false); 
        }
    }



    string? operID = "DUMMY"; // null;
    public string? OperID
    {
        get 
        {
            return operID;
        }

        set
        {
            operID = value;

            if (localStorage != null)
            {
                localStorage.SetItemAsync("OperID", value);
            }
        }

    }
}

由于您使用的是服务器端 Blazor,并且预渲染设置可能处于活动状态,因此您不能也不应该使用 OnIntialized 或 OnInitializedAsync 方法。相反,您应该使用 OnAfterRenderAsync 方法,这是使用 JSInterop 的合适位置。你的代码应该包含在一个 if 语句中,检查这是否是第一次渲染,像这样:

protected override async Task OnAfterRenderAsync(bool firstRender)
    {    if( firstRender)
         {   
             await model.InitializeAsync(localStorage);
             // And of course the StateHasChanged method should be called here to refresh the page.
             StateHasChanged(); 
          }
    }

这样您的模型只会被初始化一次,而不是每次执行 OnAfterRenderAsync 时,也就是页面组件需要重新呈现时。

注意:如果您正在重新渲染,则根本不会调用 OnAfterRenderAsync 方法。

_Host.cshtml 中的以下代码片段可以判断您是否正在使用预渲染:

<app>
     <component type="typeof(App)" render-mode="ServerPrerendered" />   
</app>

正如您从设置中看到的那样,您的应用正在服务器上预呈现。 Blazored.LocalStorage 是否支持数据保护,如果不支持。使用 Blazor 团队创建的库。

这是我为使其生效而更改的代码:

protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender) // prevent infinite loop
        {         
            await model.InitializeAsync(localStorage); // load data

            StateHasChanged();  // update view

        }
    }