必须在脚手架模板中硬编码可访问性结构,如<main>作为唯一顶层容器、<nav aria-label>强制带值、<img>绑定必传altTextprop,因ESLint和html-validate仅报错无法阻止错误模板生成,且CI拦截滞后于开发体验。

直接在脚手架生成阶段把 <main>、<nav aria-label>、alt 约束等可访问性要求“焊死”进模板文件里,而不是靠文档或口头提醒——否则 90% 的新项目会在第一版就漏掉 <main> 或写错 aria-label。
为什么不能只靠 ESLint 或 html-validate 检查
这些工具只能报错,不能阻止错误模板被创建。比如脚手架生成的 App.vue 里默认用 <div id="app"> 包裹全部内容,<main> 根本没出现;又比如 <img> 标签生成时缺 alt 属性,html-validate 虽能捕获,但 PR 已经提了,修复成本远高于初始约束。
- html-validate 默认不校验
.vue或.tsx里的模板片段,需额外配vite-plugin-html-validate或html-validate-loader - ESLint 插件(如
eslint-plugin-jsx-a11y)对<main>嵌套、<nav>缺aria-label这类结构性问题覆盖有限 - CI 阶段拦截 ≠ 开发体验:开发者看到红 CI 才改,不如一开始就看不到错误选项
脚手架模板文件必须硬编码的可访问性结构
不是加个注释或文档说明,而是让模板本身无法合法写出错误结构。
-
<main>必须作为顶层语义容器出现在每个页面级组件根节点,且仅出现一次:<template><main>...</main></template>—— 不允许用<div role="main">替代 -
<nav>必须带aria-label,脚手架生成时固定写成:<nav aria-label="主导航">...</nav>,不提供空<nav>模板 -
<img>标签禁止裸写,模板中统一为:<img :src="avatarUrl" :alt="altText || ''">,并强制altText为必传 prop(TS 接口定义) - 所有表单控件必须配
<label for="xxx">,脚手架生成的<input>模板自带id和for绑定逻辑,不提供无 label 的版本
如何防止开发者绕过模板约束
光有正确模板不够,要堵住常见绕过路径。
立即学习“前端免费学习笔记(深入)”;
- 禁用全局
innerHTML直接赋值:在脚手架的 ESLint 配置里启用eslint-plugin-no-inner-html,拦截el.innerHTML = '<img src=x>'类动态 HTML - 禁止手动拼接
<template>字符串:模板字符串里出现`<main>${title}</main>`就报错,强制走template.content.cloneNode(true)+textContent安全填充 - 对
v-html和dangerouslySetInnerHTML做白名单控制:脚手架内置的renderHTML()工具函数只接受预设安全标签(p、strong、ul),其余一律过滤 - CLI 初始化时生成
accessibility.md文档,但关键条目同步写入tsconfig.json的compilerOptions.types,让类型系统参与约束(例如type AltText = string & { __brand: 'alt-text' })
最易被忽略的点是:脚手架生成的模板里写了 <main>,但开发者复制粘贴时删掉了它,或者把整个组件塞进另一个 <section> 里——这需要配合构建时的静态分析(如 html-validate + 自定义 rule)在 dev server 启动时实时扫描,而不是等到 CI。



















