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
}