如何告知或允许 Blazor 从未更改的绑定值中"refresh" HTML 元素?



当我在HTML元素上有一个单向绑定,并且在onchange上附带的绑定并不总是改变它,那么我如何告诉或允许Blazor"刷新";元素的值从它的绑定值开始没有改变?

StateHasChanged()不起作用,可能是因为Blazor检测到没有更改。

极简但荒谬的例子(注意现实世界的情况并不荒谬):

@page "/"
<select value="@Foo" @onchange="Update">
<option>First</option>
<option>Second</option>
</select> 
<div>
Value of Foo: @Foo
</div>
@code {
private string Foo {get;set;} = "First";
private void Update(ChangeEventArgs args) {
return; // doesn't actually change it
}
}

因此,HTML元素中的新值在更改时立即显示,但绑定的值实际上永远不会更改。这里的工作演示:我如何获得下拉列表的值保持(或更改回)"First",这是存储在Foo中的未更改的值?

最简单的方法是给元素一个@key,当您想要强制刷新时更改它。但是,这将完全破坏并重新创建元素,因此它可能是昂贵的。

@page "/"
<select @key="@Forced" value="@Foo" @onchange=@( e => Update(e) )>
<option>(none)</option>
<option>First</option>
<option>Second</option>
</select> 
@code {
private string Foo {get;set;} = "First";
private int Forced {get;set;} = 0;
private Task Update(ChangeEventArgs args) {
if (1 == 1){ // placeholder for other logic 
Forced++; // doesn't actually change it
}
else
{
Foo = args.Value.ToString() ?? "(none)";
}
return Task.CompletedTask; 
}
}

更新演示

问题在于Renderer和Diffing引擎。

该值在浏览器DOM中改变了,但在渲染器DOM中没有改变。这是两人"合法"得到的为数不多的场合之一。在Blazor中不同步。因此,当您将值更改回原来的值时,Diffing引擎看不到任何差异,因此不会向浏览器DOM发送任何更新。在构建只允许某些输入字符的文本框时,您会看到类似的情况。

我知道的唯一解决方案是利用Blazor UI事件处理程序的异步行为。

  1. 将值设置为不同的值-我通常使用String.Empty2。生成控制,以便UI可以使用Task.Delay
  2. 进行更新
  3. UI处理器调用StateHasChanged并更新UI。
  4. 设置为你想要的值
  5. UI处理程序执行最终的StateHasChanged并将输入更新为正确的值。
@page "/"
<div>
Foo: <select value="@Foo" @onchange="Update">
<option>(none)</option>
<option>First</option>
<option>Second</option>
</select> 
</div>
<div>
Value of Foo: @Foo
</div>
@code {
private string Foo {get;set;} = "First";
private async Task Update(ChangeEventArgs args) {
Foo = string.Empty;
await Task.Delay(1);
Foo = "First";
}
}

如果我理解你的要求,试试这段代码,它将显示Foo

的选定值
<select value="@Foo" @onchange="@(e=> Foo=e?.Value?.ToString())">
<option value="(none)">(none)</option>
<option value="First">First</option>
<option value="Second">Second</option>
</select> 

相关内容

  • 没有找到相关文章

最新更新