<p>应避免内联 onclick,改用 data-action 钩子配合事件委托;tabindex 需搭配 role 和 aria-* 保证语义与可访问性;loading="lazy" 和 decoding="async" 要合理应用以优化加载性能。</p>
onclick 绑定点击行为,但别直接写 JS 代码直接在 HTML 里写 onclick="doSomething()" 看似方便,实际会让逻辑和结构混在一起,改个按钮行为就得翻 HTML,JS 也难复用。
更稳妥的做法是只留行为钩子,比如加一个 data-action="toggle-menu",再用 document.addEventListener('click', ...) 统一监听。这样 JS 集中管理,HTML 干净,后续加埋点、权限控制也容易。
onclick="alert('ok')" 这类内联脚本,尤其在团队项目或需要 SEO 的页面中onclick="console.log(this)" 查看当前元素,但上线前要删掉this 在内联 onclick 中指向触发元素,但箭头函数里会失效,注意上下文tabindex 控制键盘焦点顺序,不是只给 div 加就能用设 tabindex="0" 确实能让非表单元素获得 Tab 焦点,但光有这个不够——用户按 Enter 或 Space 时不会自动触发行为,得手动监听 keydown 并判断按键码。
更关键的是语义缺失:屏幕阅读器不会把 div tabindex="0" 当作可交互控件,除非同时加 role="button" 和 aria-label。
立即学习“前端免费学习笔记(深入)”;
tabindex="-1" 常用于 JS 动态聚焦(如模态框打开后聚焦首元素),它不可通过 Tab 进入,但可通过 focus() 调用button、a、input 默认可聚焦且语义明确,优先用它们,而不是“造轮子”tabindex="0" 的元素,务必补上 role 和 aria-* 属性,否则对辅助技术用户不友好aria- 属性不是装饰,该加的必须加,不该加的别硬套aria-hidden="true" 会彻底隐藏元素及其子树,连屏幕阅读器都读不到。常见误用是给 loading 遮罩层加这个,结果导致遮罩下的内容仍可被读出,或者遮罩本身无法被感知。
真正该用的场景是:图标字体(无文本)、纯装饰性图片、动态加载中的占位符等确实不需要被辅助技术识别的内容。
aria-live="polite" 适合通知类区域(如表单提交成功提示),但频繁更新会打断屏幕阅读器朗读,慎用aria-expanded 必须和 aria-controls 配合使用,且值要实时同步(JS 改变展开状态时,属性值也要同步改)h1~h6 加 aria-level,标题层级由标签本身决定,加了反而干扰loading="lazy" 和 decoding="async" 对图片加载体验影响明显这两个属性不是锦上添花,而是直接影响首屏渲染速度和滚动流畅度。尤其是长列表中的图片,没加 loading="lazy" 会导致页面加载时大量请求并发,拖慢主资源下载。
decoding="async" 让浏览器在后台解码图片,避免阻塞主线程,对大图或高 PPI 设备效果更明显。但注意:Safari 直到 iOS 17.4 才完全支持 decoding,旧版本会忽略。
loading="lazy" 对 img 和 iframe 有效,但不适用于 CSS 背景图(需用 Intersection Observer 替代)loading="lazy",否则可能因懒加载时机晚而闪动width 和 height 属性,能防止图片加载时布局偏移(CLS 问题)真实项目里,交互体验的瓶颈往往不在动画多炫,而在焦点是否自然、提示是否及时、加载是否克制。这些细节不显眼,但用户一旦遇到卡顿、跳读、误操作,第一反应就是“这网页不靠谱”。tabindex、aria-、loading 这些属性看着零碎,其实是把控制权从“浏览器默认”收回到“开发者明确声明”的过程——少一点假设,多一点确定性。