输入元素不会重新渲染,用例是当用户输入一些文本时,当前日期将通过“ value
”属性填充到输入元素中。请参阅下面的代码。
@page "/"
<label>Text Binding check:</label>
<input type="text" value="@TextData" @onchange="OnChange_Text" />
<br />
<br />
<label>Text Dummy:</label>
<input type="text" value="dummy" />
@code
{
public string? TextData { get; set; } = "12-12-2022";
protected override bool ShouldRender()
{
return true;
}
private void OnChange_Text(ChangeEventArgs e)
{
TextData = GetValue(e.Value?.ToString());
InvokeAsync(() => StateHasChanged());
}
private string GetValue(string? strValue)
{
return strValue switch
{
"test" => DateTime.Now.ToString("dd-MM-yyyy"),
"data" => DateTime.Now.ToString("dd-MM-yyyy"),
"nash" => DateTime.Now.ToString("dd-MM-yyyy"),
_ => DateTime.Now.ToString("dd-MM-yyyy")
};
}
}
如果用户再次输入相同的文本或任何文本,则日期不会第二次呈现在输入元素中。即使将 和StateHasChanged()
设置ShouldRender
为 true,也不会呈现该值。
因此,根据 Blazor 机制,元素实际上并未改变,因此渲染树不会将输入元素渲染到 DOM。我该如何解决这个问题,如何重新渲染未改变的元素?我想SateHasChanged()
刷新ShouldRender
UI,它不关心元素差异。
我假设这是一个交互式页面。
使用
@bind
和@bind:after
。让绑定和 UI 事件处理程序完成工作。绑定回调 [设置
TextData
] 是一个 UI 事件。它设置值,然后调用已注册的after
方法。最后调用StateHasChanged
以呈现新状态。我修改了生成的日期和格式,以便更容易看到不同的结果。
就我个人而言,除非真的找不到替代或可行的解决方案,否则在使用 Blazor 时我会避免使用 JS。Blazor 已经提供了所有内容,因此我们可以继续使用 C#。
首先,您需要为页面提供交互性,否则更改将无法呈现(至少对于较新的 .NET 和 Blazor 版本)。可以使用以下行激活此功能
@rendermode InteractiveServer
。为什么不使用标准
InputText
组件?在这里,您可以将值绑定到属性并直接更新它。这也让 Blazor 知道某些东西已经发生了变化。只有在需要时才应该调用StateHasChanged,因为 Blazor 知道何时发生了变化(子组件的情况不同)。如果您不想直接在属性中包含逻辑,那么您也可以将其外包给方法并在 InputText 组件中使用相应的属性(但在我看来它看起来不那么有吸引力)
当然,这不是实现您所看到功能的方法。只需使用
@bind-Value
和@bind-Value:after
这可能是由于 blazor 组件渲染中的优化。我用你的代码在我这边进行了测试,我也发现 的原始值为
TextData
,12-12-2022
然后当我们data
在输入字段中输入时,TextData
它将更改为DataTime.Now
。26-08-2024
下次我们更改输入值时,它将更改为 ,26-08-2024
实际上不会改变值。那么可能是由于某种优化,即使我们调用StateHasChanged()
,它也不会重新渲染页面。我的解决方法是使用 JS 直接更新 DOM。
并将下面的 js 放在
<script src="_framework/blazor.server.js"></script>
in后面_Layout.cshtml
,因为您的标签是 blazor server。如果您拥有的是 blazor web app,那么它应该是<script src="_framework/blazor.web.js"></script>
中的App.razor
。