单页应用路由跳转后焦点未落到主内容区,因dom尚未就绪;应设main元素tabindex="-1",vue用onmounted+settimeout(() => el.focus(), 0),react用useeffect+ref校验,配合aria-live="polite"播报。

单页应用路由跳转后焦点没落到主内容区
页面切换后 focus() 静默失败,不是代码写错了,而是 DOM 还没准备好——Vue/React 的异步渲染会让元素在调用时仍处于挂载前状态。直接在路由守卫或组件 mounted/useEffect 里调 focus(),大概率失效。
实操建议:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 在目标容器(如
<main id="main-content"></main>)上设tabindex="-1",**不能用tabindex="0"**,否则它会混入 Tab 流,破坏键盘导航顺序 - Vue 中用
onMounted+setTimeout(() => el.focus(), 0)(绕过微任务队列,比nextTick更稳) - React 中用
useEffect+ref,但必须等ref.current不为null且已 commit,避免在 render 阶段调用 - 配合
aria-live="polite"向屏幕阅读器播报页面变更,例如:<main id="main-content" tabindex="-1" aria-labelledby="page-title" aria-live="polite"></main>
模态框打开时焦点没进框内或 Tab 键直接逃逸
浏览器不会自动把焦点塞进弹窗,哪怕用了 <dialog></dialog> 或 showModal()。用户按 Tab 仍从页面顶部开始,对键盘用户等于“看不见弹窗”。更糟的是,Tab 键穿过弹窗跑到背景去,形成焦点逃逸。
实操建议:
- 打开模态框后,用
requestAnimationFrame()延迟一次绘制再聚焦,比setTimeout(, 0)可靠:先查modal.querySelector('button, input, select, [tabindex="0"]'),再调.focus() - 预先缓存所有可聚焦元素:
const focusables = modal.querySelectorAll('button, input, select, [tabindex="0"]'),用于后续循环逻辑 - 监听模态框容器的
keydown,仅当event.key === 'Tab'且当前焦点在首/末元素时,event.preventDefault()并手动跳转到对应端点 - 别依赖
:focusable伪类(Safari 不支持),用getComputedStyle(el).display !== 'none' && getComputedStyle(el).visibility !== 'hidden'辅助过滤
动态插入内容(如折叠面板、搜索结果)后焦点丢失
innerHTML 插入、React/Vue 动态渲染后立即 focus(),常因浏览器尚未完成布局或焦点管理未就绪而失败。错误日志里看不到报错,但光标就是不出现。
实操建议:
- 原生 JS 场景下,插入节点后立刻用
requestAnimationFrame(() => input.focus()),它能确保在下一帧渲染前执行 - 对 Shadow DOM 内元素,先确认
shadowRoot已挂载,再查子节点并聚焦 - 非表单容器(如
<div class="card">)要支持程序聚焦,加 <code>tabindex="-1";若还需参与 Tab 导航,则用tabindex="0" - 禁用或
display: none的元素即使有tabindex也不会被聚焦,注意排查 CSS 隐藏状态 - 打开前记录触发元素:
const trigger = event.target; modal.dataset.triggerId = trigger.id;或用ref保存引用 - 关闭后优先恢复到触发源:
trigger.focus({ preventScroll: true });若触发源已销毁(如列表项被删),再 fallback 到主内容区占位元素 - Tooltip 类浮层需在卸载前主动转移焦点:
onBlur里先更新状态、再requestAnimationFrame调nextEl.focus() - 避免用
autofocus——它只允许每页一个,且无法响应动态场景,易导致不可预测的焦点跳跃
关闭模态框或折叠面板后焦点没回退到触发源
模态框关了,焦点却落在页面顶部或随机位置,键盘用户得重新按十几次 Tab 才能回到原来的操作点——这直接破坏操作连续性,尤其对屏幕阅读器用户是严重体验断裂。
实操建议:










