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

如何在Blazor/C#中不使用JavaScript,按下ESC键时取消按钮焦点?

在Blazor中实现无JS依赖的ESC关闭Tooltip功能

我正在Blazor框架中开发一个Tooltip组件,需求是当按钮处于焦点状态时按下ESC键,Tooltip会消失。目前已通过JavaScript实现该功能,但希望移除对JS的依赖。

当前实现代码

@inject IJSRuntime JSRuntime

<button @onclick="ToggleTooltip">test</button>
<div role="tooltip" @ref="tooltip" tabindex="0" @onkeydown="CloseTooltip">
  Password Rules:
</div>
<p>test</p>

@code {
  ElementReference tooltip;
  bool showTooltip = false;

  void ToggleTooltip()
  {
    showTooltip = !showTooltip;
    if (showTooltip)
    {
      tooltip.FocusAsync();
    }
  }

  async Task CloseTooltip(KeyboardEventArgs e)
  {
    if (e.Key == "Escape")
    {
      showTooltip = false;
      await JSRuntime.InvokeVoidAsync("Blurred", tooltip);
      await InvokeAsync(StateHasChanged);
    }
  }
}

<script>
  window.Blurred = function(element) {
  element.blur();
};
</script>

<style>
  * {
    margin: 0;
    padding: 0;
  }

  [role="tooltip"] {
    margin-top: .75rem;
    display: none;
    position: absolute;
    background: black;
    color: white;
  }

  [role="tooltip"]:before {
    margin-top: -7px;
    content: "";
    border: 7px solid transparent;
    border-bottom-color: #000;
    border-top-width: 0;
    position: absolute;
  }

  button:hover + [role="tooltip"],
  button:focus + [role="tooltip"],
  [role="tooltip"]:focus {
    display: block;
  }
</style>

无JS依赖的解决方案

核心是用Blazor内置的焦点管理API替代JS操作,同时通过状态绑定控制Tooltip显示,避免依赖元素的:focus状态来控制UI。

修改后的完整代码

<button @onclick="ToggleTooltip" @ref="triggerButton">test</button>
<div role="tooltip" @ref="tooltip" tabindex="0" @onkeydown="CloseTooltip" class="@(showTooltip ? "show" : "")">
  Password Rules:
</div>
<p>test</p>

@code {
  ElementReference tooltip;
  ElementReference triggerButton;
  bool showTooltip = false;

  void ToggleTooltip()
  {
    showTooltip = !showTooltip;
    if (showTooltip)
    {
      _ = tooltip.FocusAsync();
    }
    else
    {
      _ = triggerButton.FocusAsync();
    }
  }

  async Task CloseTooltip(KeyboardEventArgs e)
  {
    if (e.Key == "Escape")
    {
      showTooltip = false;
      await triggerButton.FocusAsync();
    }
  }
}

<style>
  * {
    margin: 0;
    padding: 0;
  }

  [role="tooltip"] {
    margin-top: .75rem;
    display: none;
    position: absolute;
    background: black;
    color: white;
  }

  [role="tooltip"]:before {
    margin-top: -7px;
    content: "";
    border: 7px solid transparent;
    border-bottom-color: #000;
    border-top-width: 0;
    position: absolute;
  }

  button:hover + [role="tooltip"],
  button:focus + [role="tooltip"],
  [role="tooltip"]:focus,
  [role="tooltip"].show {
    display: block;
  }
</style>

关键修改说明

  1. 移除JS依赖:删掉IJSRuntime注入和JS脚本,改用triggerButton.FocusAsync()把焦点移回触发按钮,自动让Tooltip失去焦点。
  2. 状态驱动UI:给Tooltip绑定class="@(showTooltip ? "show" : "")",通过布尔值直接控制显示状态,不再完全依赖CSS选择器。
  3. 简化更新逻辑:showTooltip变更后Blazor会自动刷新UI,不需要手动调用StateHasChanged。
  4. 保留原有交互:保留了hover、focus等触发逻辑,确保原有用户体验不变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 03:52:32