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,记录为什么这是假状态。
练习
- 完成一次鼠标点击和一次键盘操作,记录按钮的
aria-expanded、面板的hidden与当前焦点;三者不一致时指出是哪一条状态更新漏掉了。 - 删除
aria-controls或只更新属性不更新面板,预测 Accessibility 面板和键盘用户分别会看到什么。 - 把动态结果改成
role="status"的 live region,说明什么时候应该播报,什么时候应保持静默以避免重复朗读。
下一步
完成答案核对后继续本章下一篇,并把实验日志保存在自己的项目中。