data-*属性不提供可访问性信息,ARIA属性必须直接写在元素上并由JS实时同步;拼写错误、布尔值误用或仅靠dataset赋值均会导致失效。

data-* 属性不能自动传递可访问性信息
data-* 属性本身对屏幕阅读器、键盘导航或任何辅助技术完全透明——它既不触发 aria 属性更新,也不影响 role、aria-expanded 或 aria-hidden 的行为。你写了 data-aria-label="搜索框",但 screen reader 依然读不到;data-aria-expanded="true" 不会让元素获得展开语义。可访问性属性必须直接写在元素上,且由 JS 主动同步。
ARIA 属性需手动映射到 DOM 元素
组件初始化时,不能依赖 dataset 自动填充 ARIA 值。比如自定义 <search-input> 接收 data-aria-label,必须在 connectedCallback 或 attributeChangedCallback 中显式设置:
if (name === 'data-aria-label') {
this.input.setAttribute('aria-label', newValue || '');
}-
aria-属性名必须与标准一致:aria-labelledby不能写成aria-labelby,拼错就失效 - 布尔型 ARIA 值(如
aria-hidden)只认字符串"true"或"false",写成true/false(布尔值)会被转成"true"/"false",但部分旧浏览器会忽略 - 动态更新时,别用
el.dataset.ariaLabelledby = 'id1'—— 这不会设置aria-labelledby,也不会触发任何变化
role 和 aria-* 必须随状态实时同步
可访问性不是“设一次就完事”。例如轮播组件切换项时,aria-current="true" 要从旧项移除、加到新项;标签页切换时,aria-selected 和 tabindex 必须联动更新。常见疏漏:
- 只改了视觉 class,没同步
aria-selected,导致 screen reader 仍读旧状态 - 用
innerHTML替换整个面板,却忘了重置aria-hidden和tabindex - 在 Shadow DOM 中设置
aria-属性,但未通过this.shadowRoot.querySelector(...)定位到目标元素,而是误设在 host 上
避免用 data-* 模拟 ARIA 语义
有人试图用 data-role="button" + JS 注入 role="button",这不可靠:JS 失败时,语义彻底丢失;SSR 或预渲染页面中,该逻辑根本没执行。正确做法是:
立即学习“前端免费学习笔记(深入)”;
- 初始 HTML 就写真实
role和aria-属性,哪怕值是占位符(如aria-label="loading...") - 用
data-component标识组件边界,而非替代 ARIA - 构建时校验:CI 流程扫描所有
[data-component]元素,强制要求含role或至少一个aria-属性
真正容易被忽略的是:可访问性属性不是“锦上添花”,它是组件 DOM 结构的刚性组成部分——和 data-component 一样不可省略,但不像它那样只供 JS 读取;它直接参与浏览器无障碍树的构建,一旦缺失或错配,修复成本远高于样式或逻辑 bug。



















