【问题标题】:Blazor onclick from child component does not cause rerender来自子组件的 Blazor onclick 不会导致重新渲染
【发布时间】:2020-02-15 21:18:08
【问题描述】:

我有一个带有一个子组件的组件

<MyBtn Command="@ShowBusyCommand"></MyBtn>

@if(IsBusy)
{
<span>I'm busy</span>
}

@code{
 public bool IsBusy { get; set; }

 public ICommand ShowBusyCommand => RegisterCommand(() => ShowBusyCommand, CanExecute, ExecuteAsync);

 public async Task ExecuteAsync()
    {
        try
        {
            IsBusy = true;
            await Task.Delay(2000);
        }
        finally
        {
            IsBusy = false;
        }
    }
}

和 MyBtn 组件

<button @onclick="@Execute">Show busy</button>

@code {
    [Parameter]
    public ICommand Command { get; set; }

    public void Execute()
    {
        Command.Execute(null);
    }
}

当我点击按钮 ExecuteAsync 方法被执行但视图没有改变。我没有看到带有“我很忙”的文本。

我什至尝试在 MyBtn 中创建 EventCallback

<button @onclick="@OnClickHandler">Show busy</button>

@code {
    [Parameter]
    public ICommand Command { get; set; }

    [Parameter] 
    public object Receiver { get; set; }

    public async Task OnClickHandler()
    {
        var onClick = EventCallback.Factory.Create(Receiver, () => Command.Execute(null));
        await onClick.InvokeAsync(null);
    }
}


  <MyBtn Command="@ShowBusyCommand" Receiver="this"></MyBtn>

但这也无济于事。

我不明白为什么单击组件中的按钮时父状态没有改变,我该如何解决这个问题? 除了在 IsBusy 属性更改时手动调用 StateHasChanged。

如果我在 MyBtn 组件中将参数从 ICommand 更改为 EventCallback 并传递 ExecuteAsync 方法,它就可以工作。为什么?如何通过将 ICommand 作为参数传递并调用 Execute 方法使其工作?

编辑: 我刚刚发现如果我从 EventCallback 工厂中删除 lambda,它可以工作,但我不知道为什么

var onClick = EventCallback.Factory.Create(Receiver, Command.Execute);

【问题讨论】:

    标签: blazor blazor-server-side blazor-client-side


    【解决方案1】:

    这是您问题的有效代码...

    Index.razor

    @page "/"
    
    <MyBtn Func="@ShowBusyAsync"></MyBtn>
    
    @if(IsBusy)
    {
    <span>I'm busy</span>
    }
    
    @code{
     public bool IsBusy { get; set; }
    
     public async Task ShowBusyAsync(int delay)
        {
            try
            {
                IsBusy = true;
                await Task.Delay(delay);
            }
            finally
            {
                IsBusy = false;
            }
        }
    }
    

    MyBtn.razor

    <h3>MyBtn</h3>
    
    <button @onclick="@ExecuteAsync">Show busy</button>
    
    @code {
        [Parameter]
        public EventCallback <int> Func { get; set; }
    
        public async void ExecuteAsync()
        {
            await Func.InvokeAsync(3000);
        }
        }
    

    注意:如果您希望重新渲染父组件,则应使用 EventCallback,因为 EventCallback 创建了一个委托,其 Target 属性设置为注册事件的对象,即父组件。如果您不希望父组件成为事件的目标,请改用 Action 或 Func 委托。

    【讨论】:

      猜你喜欢
      • 2020-02-13
      • 1970-01-01
      • 1970-01-01
      • 2020-04-18
      • 2021-01-17
      • 2018-08-20
      • 1970-01-01
      • 2021-11-21
      • 2018-11-16
      相关资源
      最近更新 更多