传递给 Blazor 非组件的操作不会更新父组件,直到其他内容更新

  • 本文关键字:组件 更新 其他 Blazor 操作 blazor
  • 更新时间 :
  • 英文 :


如果我有一个名为DoAction的Blazor组件,它只包含以下内容…

@code {
public void DoItNow(Action action) =>
action();
}

…我在另一个组件中使用它,如下所示…

<p>@((MarkupString)_msg)</p>
<br/><button @onclick="DoItNow">Do it now</button>
<DoAction @ref="_doAction" />
@code {
private string _msg;
private DoAction _doAction;
private void DoItNow() =>
_doAction.DoItNow(() => _msg += $"<br/>{DateTime.Now.ToLongTimeString()}: DoItNow");
}

…那就没问题了。我可以点击按钮,显示就会更新。

然而,如果我改变这一点,使DoAction显示一个按钮,只有当按钮被点击时才执行动作,它不工作,见下文。

更新DoAction组件…

<button class="btn btn-primary" @onclick="ButtonClicked">Click me</button>
@code {
private bool _showButton = false;
private Action _action;
public void DoItAfterButtonClick(Action action) {
// Hold on to the action for use below
_action = action;
_showButton = true;
}
private void ButtonClicked() {
_action();
_showButton = false;
}
}

更新父组件…

<p>@((MarkupString)_msg)</p>
<br/><button @onclick="DoItAfterButtonClick">Do it after button click</button>
<DoAction @ref="_doAction" />
@code {
private DoAction _doAction;
private void DoItAfterButtonClick() =>
_doAction.DoItAfterButtonClick(
() => _msg += $"<br/>{DateTime.Now.ToLongTimeString()}: DoItAfterButtonClick");
}

…然后,当我单击父组件中的按钮时,出现DoAction组件中的按钮,但是当我单击该按钮时,在其他东西更新UI之前什么都不会发生。此时,我看到了当我单击DoAction组件的按钮时没有显示的消息。

我尝试在DoAction中添加对StateHasChanged()的调用,但它没有任何区别。我能让它工作的唯一方法是,如果我在父组件中调用StateHasChanged()

private void DoItAfterButtonClick() =>
_doAction.DoItAfterButtonClick(
() => {
_msg += $"<br/>{DateTime.Now.ToLongTimeString()}: DoItAfterButtonClick";
StateHasChanged();
});

有人知道为什么UI没有在第二种情况下更新吗?

欢迎…

我不太明白你想达到什么目的。我建议你现在不要这样做,以后也不要……

注意:Action委托封装了父组件拥有的方法(代码),而不是DoAction组件,并且它只从DoAction组件执行

在第一个版本中当你点击"DoItNow"按钮时,从DoAction组件调用委托,呈现过程通知父组件事件已经发生(调用stathaschanged方法),并且它应该重新呈现。请注意,当涉及到UI事件时,框架会自动调用StateHasChanged方法,就像当前单击"doitnow"的情况一样。按钮

public void DoItNow(Action action) =>
action();

父组件被重新呈现,因此显示得到更新。

在第二个版本中,当单击"ButtonClicked"按钮时调用Action委托_action,呈现进程通知DoAction事件已经发生(调用StateHasChanged方法;再次是UI事件),它应该重新渲染。DoAction组件当然会被重新渲染,ButtonClicked"按钮,如您所见,在设置:_showButton = false;后没有呈现,但是父组件不知道这一点。父组件不知道它所经历的变化,因为调用了封装了它所拥有的(方法)代码的Action委托…

解决方案当然是像这样添加StateHasChanged方法:
_doAction.DoItAfterButtonClick(
() => { _msg += $"<br/>{DateTime.Now.ToLongTimeString()}: DoItAfterButtonClick"; StateHasChanged(); }); 

当然你已经找到解决方案了…我希望现在你已经找到了为什么UI没有在第二种情况下更新的解释…

奖金:

尽可能使用EventCallback 'delegate'…使用组件参数…你可以在DoAction中定义一个EventCallback组件参数,当它被调用时,可以在父组件上执行代码,而不需要调用StateHasChanged方法,也不会对这里发生的事情感到困惑……

相关内容

  • 没有找到相关文章

最新更新