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

Vuetify v-select焦点切换时屏幕阅读器重复播报选中项问题求助

Vuetify v-select 屏幕阅读器无障碍问题:Tab切换时重复播报选中项

问题描述

在Vue 3项目中使用Vuetify的v-select组件时,遇到屏幕阅读器(NVDA、VoiceOver)的无障碍异常:选中选项后按Tab键将焦点移至下一个元素(如按钮),屏幕阅读器会先播报之前选中的选项,再播报当前聚焦的元素。原生<select>无此问题,期望切换焦点后直接播报当前聚焦元素的标签。

代码示例

<template>
  <v-app>
    <v-container>
      <button>Click me</button>
      <v-select
        label="Select"
        :items="['California', 'Colorado', 'Florida', 'Georgia', 'Texas', 'Wyoming']"
      ></v-select>
      <button>test</button>
    </v-container>
  </v-app>
</template>

<script setup>
import { ref } from 'vue'

const msg = ref('Hello World!')
</script>

解决方案

方法1:调整菜单关闭后的焦点行为

通过menu-props配置关闭菜单时不返回焦点到选择器,避免触发额外的选中项播报:

<v-select
  label="Select"
  :items="['California', 'Colorado', 'Florida', 'Georgia', 'Texas', 'Wyoming']"
  :menu-props="{ returnFocusOnClose: false }"
></v-select>

注意:此设置会改变默认的焦点返回逻辑,需验证是否符合自身无障碍需求。

方法2:监听Blur事件重置ARIA属性

在选择器失焦时,手动重置可能导致重复播报的ARIA属性:

<template>
  <v-app>
    <v-container>
      <button>Click me</button>
      <v-select
        ref="selectRef"
        label="Select"
        :items="['California', 'Colorado', 'Florida', 'Georgia', 'Texas', 'Wyoming']"
        @blur="handleSelectBlur"
      ></v-select>
      <button>test</button>
    </v-container>
  </v-app>
</template>

<script setup>
import { ref } from 'vue'

const selectRef = ref(null)
const msg = ref('Hello World!')

const handleSelectBlur = () => {
  const inputEl = selectRef.value?.$el.querySelector('input')
  if (inputEl) {
    // 重置aria-label为原始标签,清除选中项相关的临时播报内容
    inputEl.setAttribute('aria-label', 'Select')
  }
}
</script>

方法3:禁用组件的实时播报属性

通过自定义指令阻止v-select设置可能触发重复播报的aria-live属性:

<script setup>
import { ref, directive } from 'vue'

// 自定义指令:抑制选择器的额外实时播报
const vSuppressAnnounce = directive({
  mounted(el) {
    const input = el.querySelector('input')
    if (input) {
      const originalSetAttr = input.setAttribute
      input.setAttribute = function(name, value) {
        // 跳过设置polite级别的aria-live属性
        if (name === 'aria-live' && value === 'polite') return
        originalSetAttr.call(this, name, value)
      }
    }
  }
})

const msg = ref('Hello World!')
</script>

<template>
  <v-app>
    <v-container>
      <button>Click me</button>
      <v-select
        v-suppress-announce
        label="Select"
        :items="['California', 'Colorado', 'Florida', 'Georgia', 'Texas', 'Wyoming']"
      ></v-select>
      <button>test</button>
    </v-container>
  </v-app>
</template>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:55:07