You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor同级事件冲突解决:点击列表项时onfocusout优先于onclick触发怎么办

解决方案

方案1:将列表项的onclick替换为onmousedown(最推荐)

click事件触发时机晚于focusout是浏览器默认行为:focusout会在鼠标按下其他元素时立刻触发,而click需要等鼠标按下+松开的完整动作完成才会触发。mousedown的触发时机早于focusout,可以直接解决优先级问题:

  • 给列表项绑定onmousedown事件替代原有的onclick
  • 在mousedown事件回调中调用event.preventDefault(),可以阻止输入框失去焦点,从根源上避免focusout触发
    示例代码(Blazor版本):
<input type="search" @onfocusout="HandleFocusOut" />
<ul class="dropdown">
  <li @onmousedown="(e) => HandleItemClick(e, item)">@item.Text</li>
</ul>

@code {
  void HandleItemClick(MouseEventArgs e, SelectItem item)
  {
      e.PreventDefault(); // 阻止输入框失焦
      // 原有点击逻辑,比如赋值给输入框、关闭下拉
  }

  void HandleFocusOut()
  {
      // 失焦关闭下拉逻辑
  }
}

方案2:给focusout逻辑添加短延迟

如果不想修改原有事件绑定,可以给focusout的执行逻辑加150~200ms的延迟,预留足够时间让click事件先执行完成:
示例代码:

@inject IJSRuntime JSRuntime

<input type="search" @onfocusout="HandleFocusOut" />
<ul class="dropdown">
  <li @onclick="HandleItemClick">List Item One</li>
</ul>

@code {
  private CancellationTokenSource? _focusOutCts;

  async Task HandleFocusOut()
  {
      _focusOutCts = new CancellationTokenSource();
      try
      {
          await Task.Delay(200, _focusOutCts.Token);
          // 原有失焦逻辑,关闭下拉
      }
      catch (OperationCanceledException)
      {
          // 点击了列表项,取消失焦逻辑
      }
  }

  void HandleItemClick()
  {
      // 先取消失焦逻辑的执行
      _focusOutCts?.Cancel();
      // 原有点击逻辑
  }
}

方案3:判断失焦的目标元素是否属于下拉区域

利用focusout事件的RelatedTarget属性,判断新获得焦点的元素是否在下拉列表内部,如果是则不执行失焦关闭逻辑:

<input type="search" @onfocusout="HandleFocusOut" />
<ul class="dropdown" @ref="_dropdownRef">
  <li @onclick="HandleItemClick">List Item One</li>
</ul>

@code {
  private ElementReference _dropdownRef;
  [Inject] private IJSRuntime JSRuntime { get; set; }

  async Task HandleFocusOut(FocusEventArgs e)
  {
      // 调用JS判断新的焦点元素是否在下拉列表内
      var isClickInsideDropdown = await JSRuntime.InvokeAsync<bool>("isElementInside", e.RelatedTarget, _dropdownRef);
      if (!isClickInsideDropdown)
      {
          // 只有失焦到下拉外部才执行关闭逻辑
      }
  }

  void HandleItemClick()
  {
      // 原有点击逻辑
  }
}

对应的JS辅助方法:

function isElementInside(target, container) {
  if (!target) return false;
  return container.contains(target);
}

内容的提问来源于stack exchange,提问作者Reptar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 01:54:05