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

如何动态设置导航抽屉的tabindex,避免关闭时被Tab键聚焦?

解决导航抽屉关闭时内部元素可被Tab选中的问题

最优方案:使用inert属性

直接给导航抽屉的容器(比如你的<nav>元素)绑定inert属性,当抽屉关闭(showDrawer为false)时启用该属性:

<nav :inert="!showDrawer">
  <!-- 抽屉内部的router-link、button等元素 -->
</nav>

inert是原生HTML属性,作用是让元素及其所有子元素无法获得焦点,同时也会被屏幕阅读器忽略,完全符合需求,无需逐个修改内部元素,代码简洁且性能友好。现代浏览器(Chrome 84+、Firefox 101+、Safari 15.4+)都已支持该属性。

兼容方案:自定义Vue指令批量处理焦点

如果需要兼容旧浏览器,可以写一个自定义指令,自动处理容器内所有可聚焦元素的tabindex状态:

  1. 注册全局指令:
app.directive('focus-lock', {
  mounted(el, binding) {
    // 收集容器内所有可聚焦元素
    const focusableElements = el.querySelectorAll(
      'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
    )
    el._focusableElements = Array.from(focusableElements)
    // 保存元素原本的tabindex值
    el._originalTabIndexes = el._focusableElements.map(el => el.getAttribute('tabindex') || null)
    // 初始化状态
    this.update(el, binding)
  },
  updated(el, binding) {
    this.update(el, binding)
  },
  update(el, binding) {
    const isLocked = binding.value
    el._focusableElements.forEach((el, index) => {
      if (isLocked) {
        el.setAttribute('tabindex', '-1')
      } else {
        // 恢复原本的tabindex,没有则移除属性(保持默认行为)
        const originalIndex = el._originalTabIndexes[index]
        if (originalIndex === null) {
          el.removeAttribute('tabindex')
        } else {
          el.setAttribute('tabindex', originalIndex)
        }
      }
    })
  },
  unmounted(el) {
    // 清理缓存
    delete el._focusableElements
    delete el._originalTabIndexes
  }
})
  1. 在组件中使用:
<nav v-focus-lock="!showDrawer">
  <!-- 抽屉内部元素 -->
</nav>

这个指令会自动识别容器内所有可聚焦元素,在抽屉关闭时设置tabindex="-1",打开时恢复原有状态,避免了逐个元素修改的繁琐。

补充说明

  • 直接给父容器设置tabindex="-1"无效的原因是:该属性只作用于容器本身,不会影响其子元素的焦点行为。
  • 避免使用display: none或移除DOM的方式,虽然能解决焦点问题,但会触发DOM重排/重绘,影响性能,你选择通过tabindex控制的思路是正确的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 02:22:16