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
相关产品推荐
相关产品推荐

