main 标签是 spa 中内容结构的固定锚点,必须唯一且静态存在,仅更新其子节点而非自身;禁止动态创建多个 main,非主内容应置于 body 下,需同步更新 title 和 aria-label 保障语义连续性。

main 标签在 SPA 中不是切换的“执行者”,而是内容结构的“固定锚点”。它不参与路由逻辑,也不随视图变化而增删,它的作用是稳定标识主体内容区域,保障可访问性和 SEO 一致性。
必须唯一且静态存在
HTML 规范明确规定:一个文档中只能有一个 main 元素,且不能嵌套在 header、nav、aside、footer 或 article 内部。SPA 中若动态创建多个 main(如每次路由跳转都 new 一个),会导致:
- 屏幕阅读器只读取第一个 main,后续内容被忽略
- 搜索引擎无法准确提取主内容,可能降权
- W3C 验证失败,document.querySelector('main') 返回不稳定结果
视图切换只操作其内部结构
所有路由变更应仅更新 main 的子节点,而不是替换 main 本身。例如:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- Vue 中 router-view 默认渲染在 main 内部,组件切换自然发生在该范围内
- React Router 的 Outlet 或自定义渲染逻辑也应挂载于 main 下
- 手动操作 DOM 时,用 innerHTML 或 replaceChildren 更新内容,而非 outerHTML 替换 main
避免在 main 外放置核心视图内容
全局弹窗、加载遮罩、Toast 提示等非主内容,不应塞进 main —— 它们属于“应用层交互”,更适合放在 body 直接子级,并配合 aria-live="polite" 实现无障碍播报。把导航栏、页脚等重复区块放在 main 外是合理的,但用户真正要读/操作的页面主体,必须包裹在唯一的 main 里。
配合路由做好语义连续性
当路由切换后,main 内容更新,建议同步更新 document.title 和 main 的 aria-label(如 aria-label="用户设置页面"),帮助辅助技术感知上下文变化。也可结合 History API 的 popstate 事件,在切换后主动聚焦 main,提升键盘用户流式体验。










