autofocus仅在HTML初始解析时生效,弹窗中需用ref+生命周期钩子聚焦;iOS Safari禁止非手势触发focus,须绑定按钮事件立即调用;软键盘不弹需focus({preventScroll:true})或临时readonly;多层弹窗需监听显示完成事件并setTimeout聚焦。

弹窗中用autofocus无效的根源
autofocus只在HTML初始解析时生效,而弹窗(display: none → block、v-if切换、React.lazy动态加载)都是DOM更新行为,浏览器早已完成解析,autofocus属性彻底失效。这不是bug,是HTML规范明确限定的行为——它不响应任何后续DOM操作。
Vue/React中弹窗聚焦必须用ref + 生命周期钩子
框架接管了渲染流程,必须等组件真实挂载、元素可见、且未被用户主动操作后再调用focus()。混用autofocus和JS聚焦反而容易冲突。
- Vue 3:用
onMounted+ref,并确保v-if条件已为true,否则inputRef.value为null - React:用
useEffect+useRef,加空依赖数组;服务端渲染需包裹if (typeof window !== 'undefined') - 务必检查
document.activeElement !== input,避免覆盖用户正在输入的其他框
iOS Safari中弹窗聚焦失败的硬性限制
iOS Safari静默忽略所有非用户手势触发的focus()调用,哪怕你已在onMounted里执行。这是Apple明确的设计策略,不是兼容性问题。
- 可靠做法:给弹窗触发按钮绑定
click或touchstart,回调中**立即**调用input.focus() - 若需自动弹出(如URL带参数打开弹窗),可监听一次
body的touchstart,preventDefault()后聚焦,但仅限首次交互 - 软键盘不弹?尝试
input.focus({ preventScroll: true }),iOS 15.4+支持;老版本可临时设readonly再移除
多个弹窗嵌套或快速开关时的焦点丢失修复
弹窗关闭又重开,或模态框内再开子弹窗,常因DOM销毁重建导致ref失效、焦点被系统重置。
立即学习“前端免费学习笔记(深入)”;
- 不要在
blur事件里强行focus()回来——视觉闪烁且破坏可访问性 - 监听弹窗“显示完成”事件:
shown.bs.modal(Bootstrap)、@show(Element Plus)、或自定义emit('shown') - 聚焦前加
setTimeout(() => input.focus(), 0),避开Vue/React的同步更新队列 - CSS上加
scroll-margin-top: 60px,防止焦点滚动后被导航栏遮挡
focus()成功 ≠ 键盘弹出,而很多测试只看document.activeElement是否匹配,就误判为“已解决”。



















