Skip to content

ARIA 状态与动态反馈 ​

先从一个浏览器可观察问题开始:同一操作为什么会改变节点、事件、请求、存储或辅助技术状态?本节把“ARIA 状态与动态反馈”拆成输入、所有者、中间状态和输出,避免只背 API。

最小实验 ​

下面的按钮、面板和脚本可以直接保存为 HTML。点击或按 Enter/Space 后,aria-expanded、hidden 和焦点目标必须保持一致。

html
<button id="toggle" type="button" aria-expanded="false" aria-controls="panel">更多</button>
<section id="panel" hidden>补充内容</section>
<script>
  const toggle = document.querySelector('#toggle')
  const panel = document.querySelector('#panel')
  toggle.addEventListener('click', () => {
    const open = toggle.getAttribute('aria-expanded') === 'true'
    toggle.setAttribute('aria-expanded', String(!open))
    panel.hidden = open
    if (!open) panel.querySelector('a,button')?.focus()
  })
</script>

打开 DevTools Accessibility 面板记录两次点击后的 expanded、hidden 和焦点;只改 aria-expanded 而不改 hidden,说明为什么这是假状态。

规则与边界 ​

  • 平台保证、浏览器实现和业务约定必须分开;一个浏览器中的结果不能自动推广到所有宿主。
  • 每个监听器、请求、观察器、缓存和焦点操作都要有清理/取消责任;页面或组件离开后不能继续写状态。
  • 用户输入、URL、HTML、消息和持久化数据按不同信任边界处理;类型正确不代表内容可信。
  • 失败、取消、超时、权限拒绝、配额不足和不支持要有不同的可观察结果。

机制拆解 ​

ARIA 状态描述已有交互语义,不会自动赋予元素键盘行为。aria-expanded 必须与按钮控制的真实区域同步,aria-busy 和 live region 也应只在状态确实变化时更新,避免读屏重复播报。

可运行实验 ​

js
const toggle = document.querySelector('#toggle')
const panel = document.querySelector('#panel')
toggle.addEventListener('click', () => {
  const open = toggle.getAttribute('aria-expanded') === 'true'
  toggle.setAttribute('aria-expanded', String(!open))
  panel.hidden = open
})

用键盘操作并在 Accessibility 面板观察 expanded/hidden 是否一致;只改 aria-expanded 而不改 hidden,记录为什么这是假状态。

练习 ​

  1. 完成一次鼠标点击和一次键盘操作,记录按钮的 aria-expanded、面板的 hidden 与当前焦点;三者不一致时指出是哪一条状态更新漏掉了。
  2. 删除 aria-controls 或只更新属性不更新面板,预测 Accessibility 面板和键盘用户分别会看到什么。
  3. 把动态结果改成 role="status" 的 live region,说明什么时候应该播报,什么时候应保持静默以避免重复朗读。

查看本节答案

下一步 ​

完成答案核对后继续本章下一篇,并把实验日志保存在自己的项目中。

用心记录每一步成长