aria-busy="true" 仅用于 role="application" 或可交互动态区域(如图表重绘),普通局部刷新禁用;须设于直接容器、配对切换、避免与 aria-live 混用,且需结合 aria-hidden 和 aria-live="polite" 确保可访问性。

aria-busy="true" 什么时候该用,什么时候不该用
它不是通用加载指示器,只适用于 role="application" 或明确可交互的动态区域(比如表格重排序、图表重绘),普通页面局部刷新(如 AJAX 替换 div)用它反而破坏屏幕阅读器流式体验。
常见错误现象:aria-busy="true" 加在根容器上,导致整个页面被“静音”;或长期不设为 false,屏幕阅读器卡在忙状态无法继续读取后续内容。
- 只加在直接承载动态内容的容器上,比如图表父
div,而非body或页眉 - 必须配对控制:AJAX 请求开始时设
aria-busy="true",成功/失败回调里立刻设回"false" - 不要和
aria-live区域混用——二者语义冲突,aria-busy会暂停 live 区域播报
图表加载中,用什么 HTML 结构最稳妥
视觉加载提示(如 spinner)本身不解决可访问性问题,必须配合语义化标记。重点不是“怎么转”,而是“让辅助技术知道‘正在加载’且‘稍后会有新内容’”。
使用场景:ECharts、Chart.js 等库完成渲染前的空白期;数据请求中图表区域不可交互但需保留占位。
- 容器设
role="region"+aria-label="销售趋势图,加载中",比纯div更明确上下文 - 加载态内部放一个
span,含aria-live="polite"和文本 “加载中…”,图表就绪后用 JS 替换该span并移除aria-live - 避免仅靠 CSS 动画 spinner:没文字、没角色、没状态反馈,对屏幕阅读器用户等于“此处什么也没有”
为什么 setAttribute("aria-busy", "true") 后,NVDA 还在读旧内容
因为 aria-busy 不触发自动播报,也不清空已缓存的 DOM 快照;它只是告诉辅助技术“别读这个区域现在的内容”,但旧内容仍留在语音队列里。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
性能影响:频繁切换 aria-busy 值本身开销极小,但若配合强制重排(如每次设 busy 都改 height 或 visibility),会拖慢图表初始化速度。
- 确保 busy 切换发生在图表容器真实内容更新之前,而不是之后
- 如果旧内容已被读出,光设
busy="true"挡不住已发出的语音;得靠aria-live="off"配合临时停用(但慎用,易丢失关键更新) - 更可靠的做法:加载开始时隐藏旧图表(
aria-hidden="true"),加载完成再显新图表并聚焦到新容器
Chart.js 渲染完成,如何安全清除 loading 状态
Chart.js 的 onResize 或 onAnimationComplete 都不可靠——前者触发太频繁,后者在无动画时根本不调;真正稳的时机是 afterDraw 钩子 + 手动标记“首次绘制完成”。
容易踩的坑:监听 chart.update() 回调,但它只表示配置已应用,不代表 canvas 已重绘完毕,尤其在高 DPI 屏幕下延迟明显。
- 在
plugins里加一个轻量钩子:afterDraw: (chart) => { if (!chart._loaded) { chart.canvas.parentElement.setAttribute('aria-busy', 'false'); chart._loaded = true; } } - 务必检查
chart.canvas.parentElement是否还存在(组件卸载时可能已销毁),否则报错中断后续逻辑 - 不要依赖
setTimeout等“猜时间”的方式——网络抖动、低端设备、图表数据量大都会让实际渲染时间飘移
动态图表的加载状态不是加个属性就完事;真正的难点在于把“JS 渲染进度”、“DOM 更新时机”、“辅助技术感知节奏”三者对齐。漏掉任意一环,loading 就变成 silent failure。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










