Blazor WASM - StateHasChanged() 未更新 UI
Blazor WASM - StateHasChanged() Not Updating UI
我在 .NET6 上使用 Blazor WASM。我正在尝试在大型菜单上过滤 link 的名称。
我有一个反应过滤器,它是一个 html 输入,并且根据输入中输入的文本,如果任何文本匹配 link 名称,[= 的匹配部分25=] 名称以红色突出显示。它工作正常,除了它需要单击鼠标(任意位置)或在过滤器中输入文本后按下回车键以使用突出显示的文本更新 UI 。我尝试在输入上引发“onkeypress”事件,它调用异步调用 StateHasChanged() 的“RefreshUI”方法(我将在下面提供一个小示例)。
我将 classes 放在 razor 文件中,以便您可以看到一个工作示例(我将它们放在单独的 class 文件中)。此处更改了 GetMenuData() 以提供较小的伪造数据集。真正的只是从网络 api 中消耗 JSON 并将其转换为对象。
我已验证事件已引发并调用了 StateHasChanged(),但我不明白为什么 DOM 没有更新。任何帮助将不胜感激。
@page "/counter"
@using System.Text.RegularExpressions
<PageTitle>Counter</PageTitle>
<ul>
<li id="filter" class="show">
<div class="form-group fg--search">
<input type="search" class="input" placeholder="Search for Menu Items..." @bind="filterTerm" @onkeypress="RefreshUI">
</div>
</li>
<li>
<a href="#">Business Metrics</a>
<ul class="business-metrics flexbox">
<li class="col3">
@if (menuItems != null)
{
foreach (SubMenu sm in menuItems.Where(x => x.MenuText == "Business Metrics").Select(x => x.Submenus).FirstOrDefault())
{
<div class="menu-div">
<ul>
<li><h6><a href="#">@sm.SubmenuText</a></h6></li>
@foreach (IntranetMenuData imd in sm.SubmenuLinks)
{
<li><a href="imd.LinkUrl">@((MarkupString)FilterMenu(imd.LinkTitle))</a></li>
}
</ul>
</div>
}
}
</li>
</ul>
</li>
</ul>
@code {
private string filterTerm;
private List<TopMenuHeading> menuItems;
protected override void OnInitialized()
{
GetMenuData();
base.OnInitialized();
}
private string FilterMenu(string link)
{
if (!string.IsNullOrWhiteSpace(link) && !string.IsNullOrWhiteSpace(filterTerm))
{
Match matchedText = Regex.Match(link, @"(?i:" + filterTerm + @")");
if (matchedText.Success)
{
return link.Replace(matchedText.Value, "<span style=\"color: #e8112d;text-decoration: underline;font-weight: 600;\">" + matchedText.Value + "</span>", StringComparison.InvariantCultureIgnoreCase);
}
else
{
return link;
}
}
else
{
return link;
}
}
private void GetMenuData()
{
IntranetMenuData imd1 = new IntranetMenuData();
IntranetMenuData imd2 = new IntranetMenuData();
List<IntranetMenuData> mItems = new List<IntranetMenuData>();
SubMenu sub1 = new SubMenu();
List<SubMenu> subMenus = new List<SubMenu>();
TopMenuHeading tmh = new TopMenuHeading();
List<TopMenuHeading> topMenuHeadings = new List<TopMenuHeading>();
imd1.LinkTitle = "Capacity Utilization";
imd2.LinkTitle = "Relieved Hours";
mItems.Add(imd1);
mItems.Add(imd2);
sub1.SubmenuText = "Capacity";
sub1.SubmenuLinks = mItems;
subMenus.Add(sub1);
tmh.MenuText = "Business Metrics";
tmh.Submenus = subMenus;
topMenuHeadings.Add(tmh);
menuItems = topMenuHeadings;
}
private async Task RefreshUI()
{
await InvokeAsync(() => StateHasChanged());
}
public class IntranetBookmarks
{
public long EmployeeNumber { get; set; }
public string Submenu { get; set; }
public string Text { get; set; }
public string Url { get;set; }
}
public class IntranetMenuData
{
public long LinkMenuId { get; set; }
public string LinkOnClick { get; set; }
public string LinkTitle { get; set; }
public string LinkUrl { get; set; }
}
public class SubMenu
{
public List<IntranetMenuData> SubmenuLinks { get; set; }
public string SubmenuText { get; set; }
public SubMenu()
{
SubmenuLinks = new List<IntranetMenuData>();
}
}
public class TopMenuHeading
{
public string MenuText { get; set; }
public List<SubMenu> Submenus { get; set; }
public TopMenuHeading()
{
Submenus = new List<SubMenu>();
}
}
}
您的按键没有触发 'Bind'。它只是要求 DOM 刷新,但您的 filterTerm 值不会改变。
默认绑定发生在 'onchange' 事件中。当您按回车键或输入失去焦点时会发生这种情况。
您要绑定 'oninput' 事件,每次输入内容更改时都会发生该事件:
<input type="search"
class="input"
placeholder="Search for Menu Items..."
@bind="filterTerm"
@bind:event="oninput">
由于这会导致触发 oninput 事件,并且 Blazor 引擎会在处理 UI 事件后自动触发 DOM 刷新,因此您应该能够删除 onkeypress 处理程序作为不需要强制刷新。
我使用 @bind-value
所以每次你在 result
中设置一个值时输入值都会改变
<input @onchange="filter()"/>
<input @bind-value="@result"/>
private string result {get;set;}
void filter(){
//Do something and set result=output
}
我在 .NET6 上使用 Blazor WASM。我正在尝试在大型菜单上过滤 link 的名称。
我有一个反应过滤器,它是一个 html 输入,并且根据输入中输入的文本,如果任何文本匹配 link 名称,[= 的匹配部分25=] 名称以红色突出显示。它工作正常,除了它需要单击鼠标(任意位置)或在过滤器中输入文本后按下回车键以使用突出显示的文本更新 UI 。我尝试在输入上引发“onkeypress”事件,它调用异步调用 StateHasChanged() 的“RefreshUI”方法(我将在下面提供一个小示例)。
我将 classes 放在 razor 文件中,以便您可以看到一个工作示例(我将它们放在单独的 class 文件中)。此处更改了 GetMenuData() 以提供较小的伪造数据集。真正的只是从网络 api 中消耗 JSON 并将其转换为对象。
我已验证事件已引发并调用了 StateHasChanged(),但我不明白为什么 DOM 没有更新。任何帮助将不胜感激。
@page "/counter"
@using System.Text.RegularExpressions
<PageTitle>Counter</PageTitle>
<ul>
<li id="filter" class="show">
<div class="form-group fg--search">
<input type="search" class="input" placeholder="Search for Menu Items..." @bind="filterTerm" @onkeypress="RefreshUI">
</div>
</li>
<li>
<a href="#">Business Metrics</a>
<ul class="business-metrics flexbox">
<li class="col3">
@if (menuItems != null)
{
foreach (SubMenu sm in menuItems.Where(x => x.MenuText == "Business Metrics").Select(x => x.Submenus).FirstOrDefault())
{
<div class="menu-div">
<ul>
<li><h6><a href="#">@sm.SubmenuText</a></h6></li>
@foreach (IntranetMenuData imd in sm.SubmenuLinks)
{
<li><a href="imd.LinkUrl">@((MarkupString)FilterMenu(imd.LinkTitle))</a></li>
}
</ul>
</div>
}
}
</li>
</ul>
</li>
</ul>
@code {
private string filterTerm;
private List<TopMenuHeading> menuItems;
protected override void OnInitialized()
{
GetMenuData();
base.OnInitialized();
}
private string FilterMenu(string link)
{
if (!string.IsNullOrWhiteSpace(link) && !string.IsNullOrWhiteSpace(filterTerm))
{
Match matchedText = Regex.Match(link, @"(?i:" + filterTerm + @")");
if (matchedText.Success)
{
return link.Replace(matchedText.Value, "<span style=\"color: #e8112d;text-decoration: underline;font-weight: 600;\">" + matchedText.Value + "</span>", StringComparison.InvariantCultureIgnoreCase);
}
else
{
return link;
}
}
else
{
return link;
}
}
private void GetMenuData()
{
IntranetMenuData imd1 = new IntranetMenuData();
IntranetMenuData imd2 = new IntranetMenuData();
List<IntranetMenuData> mItems = new List<IntranetMenuData>();
SubMenu sub1 = new SubMenu();
List<SubMenu> subMenus = new List<SubMenu>();
TopMenuHeading tmh = new TopMenuHeading();
List<TopMenuHeading> topMenuHeadings = new List<TopMenuHeading>();
imd1.LinkTitle = "Capacity Utilization";
imd2.LinkTitle = "Relieved Hours";
mItems.Add(imd1);
mItems.Add(imd2);
sub1.SubmenuText = "Capacity";
sub1.SubmenuLinks = mItems;
subMenus.Add(sub1);
tmh.MenuText = "Business Metrics";
tmh.Submenus = subMenus;
topMenuHeadings.Add(tmh);
menuItems = topMenuHeadings;
}
private async Task RefreshUI()
{
await InvokeAsync(() => StateHasChanged());
}
public class IntranetBookmarks
{
public long EmployeeNumber { get; set; }
public string Submenu { get; set; }
public string Text { get; set; }
public string Url { get;set; }
}
public class IntranetMenuData
{
public long LinkMenuId { get; set; }
public string LinkOnClick { get; set; }
public string LinkTitle { get; set; }
public string LinkUrl { get; set; }
}
public class SubMenu
{
public List<IntranetMenuData> SubmenuLinks { get; set; }
public string SubmenuText { get; set; }
public SubMenu()
{
SubmenuLinks = new List<IntranetMenuData>();
}
}
public class TopMenuHeading
{
public string MenuText { get; set; }
public List<SubMenu> Submenus { get; set; }
public TopMenuHeading()
{
Submenus = new List<SubMenu>();
}
}
}
您的按键没有触发 'Bind'。它只是要求 DOM 刷新,但您的 filterTerm 值不会改变。
默认绑定发生在 'onchange' 事件中。当您按回车键或输入失去焦点时会发生这种情况。
您要绑定 'oninput' 事件,每次输入内容更改时都会发生该事件:
<input type="search"
class="input"
placeholder="Search for Menu Items..."
@bind="filterTerm"
@bind:event="oninput">
由于这会导致触发 oninput 事件,并且 Blazor 引擎会在处理 UI 事件后自动触发 DOM 刷新,因此您应该能够删除 onkeypress 处理程序作为不需要强制刷新。
我使用 @bind-value
所以每次你在 result
中设置一个值时输入值都会改变
<input @onchange="filter()"/>
<input @bind-value="@result"/>
private string result {get;set;}
void filter(){
//Do something and set result=output
}