自定义元素默认不可访问,需手动补全四要素:明确role、提供可访问名称(aria-labelledby或aria-label)、实时同步aria状态、设置tabindex="0"并监听keydown/click事件。

自定义元素默认不被屏幕阅读器识别
defineElement 创建的 <my-button></my-button> 或 <my-slider></my-slider> 在辅助技术中就是个“空盒子”:读屏器只报“自定义元素”,不读内容、不响应 Tab 键、不支持 Enter/Space 激活。这不是 bug,是浏览器的默认行为——它不会自动赋予 role、tabindex 或语义。
必须手动补全四要素才能可访问
光写 role="button" 不够,必须同步满足以下四点,缺一不可:
-
role明确类型(如role="switch"、role="combobox") -
aria-labelledby或aria-label提供可访问名称(优先用aria-labelledby关联可见文本) -
aria-状态属性实时反映变化(如aria-checked="true"、aria-expanded="false") -
tabindex="0"+keydown监听 Enter/Space/Arrow 键,实现聚焦与操作
反例:<my-slider role="slider"></my-slider> 缺少 aria-valuenow、aria-valuemin、aria-valuemax,读屏器只能说出“滑块”,无法告知当前值或范围。
Shadow DOM 内部 ID 引用容易失效
若在 Shadow Root 里用 aria-labelledby="label-id",而 label-id 在 light DOM 中,屏幕阅读器将找不到该元素,导致名称丢失。
- 确保引用的 ID 存在于同一 DOM 树层级(都在 Shadow DOM 内,或都在 light DOM 内)
- 若需跨边界关联,改用
aria-label硬编码描述,或通过slot将 label 元素透传进 Shadow DOM - 避免在 Shadow DOM 中使用
document.getElementById()查找 light DOM 节点——它查不到
键盘事件监听不能只靠 keydown
仅监听 keydown 会漏掉某些平台行为,比如 macOS 上 VoiceOver 用户按 Control+Option+Space 触发开关,或某些读屏器对 Space 键的特殊处理。
- 始终同时监听
keydown和click(后者兼容鼠标、触控、辅助技术点击) - 在
keydown中阻止默认行为(e.preventDefault()),再手动触发状态变更 - 对
role="slider"这类控件,还需监听ArrowUp/ArrowDown等方向键,并配合aria-valuenow更新
最常被忽略的是:没把焦点管理纳入组件生命周期——比如弹出菜单后没把焦点移入,关闭后没还给触发按钮。这会让键盘用户直接“掉出”交互流。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











