autofocus仅在初始html解析时生效,后续路由切换或组件挂载均不触发;ios safari要求focus()必须在用户手势同步上下文中调用,且需确保元素可见、可交互。

autofocus 在 SPA 路由切换后根本不会执行
它只在浏览器首次解析原始 HTML 时触发一次,后续所有路由跳转、组件挂载、DOM 动态插入都不会重新评估 autofocus 属性。你看到新页面的输入框没聚焦,不是代码写错了,是浏览器按规范故意跳过——autofocus 不是监听器,也不是响应式属性。
为什么 React/Vue 模板里写 autofocus 没用
服务端渲染(SSR)或客户端 hydration 后,DOM 已构建完成;框架挂载组件时只是 JS 操作已有节点,浏览器不会再“重读” HTML 属性。哪怕你在 <input autofocus> 外面包一层 v-if="show" 或 {show && <input autofocus>},只要初始不渲染,autofocus 就彻底失效。
-
autofocus必须出现在初始 HTML 字符串中,且该元素需同步挂载、可见、未被display: none或inert包裹 - Vue 的
onMounted、React 的useEffect都发生在 DOM 已存在之后,此时autofocus早已被忽略 - Next.js App Router 客户端导航复用 DOM 节点,但
autofocus属性不会被重新触发
移动端 iOS Safari 对 focus() 的手势限制
iOS Safari 要求 input.focus() 必须发生在用户真实手势(如 click、tap、keydown)触发的同步上下文中,否则静默失败——这意味着单纯靠路由事件或挂载钩子调用 focus(),大概率无效。
- 正确做法:在用户点击“打开表单”按钮的回调里,立即或微任务中调用
inputRef.current?.focus() - 错误做法:在
useEffect(() => { inputRef.current?.focus(); }, [])中调用,无手势上下文,iOS 上白忙活 - 可加保护:先判断
if (input && document.activeElement !== input),避免打断用户正在操作的其他输入框
真正可靠的聚焦时机判断
不能只等“挂载”,还得确认元素已可交互:可见、未被 CSS 隐藏、父容器已渲染完成、无障碍状态就绪。
- 检查
input.offsetParent !== null或getComputedStyle(input).display !== 'none' - 用
requestAnimationFrame(() => input.focus())延迟一帧,避开 CSS transition 或 visibility 切换未结束 - 模态框场景下,别在
show = true后立刻focus(),等transitionend或animationend事件后再执行 - 多个输入框共存时,确保只有一个有聚焦逻辑,否则焦点可能被反复覆盖
focus() 不等于能聚焦,得让它“合法地被执行”。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











