autofocus仅在初始html解析时生效,动态插入元素无效;多元素中仅首个生效,且不可js动态设置;移动端需用户手势触发focus()才可靠。

autofocus 属性只在初始 HTML 解析时生效
页面加载时自动聚焦,首选 autofocus 属性。它写法简单:<input type="text" autofocus>,浏览器会在 DOM 解析完成、元素可聚焦时自动调用 focus()。但这个行为有硬性限制:
-
autofocus仅对初始 HTML 中已存在的元素起作用;通过innerHTML、appendChild或框架(Vue/React)动态插入的<input>会忽略该属性 - 一个页面中多个
autofocus只有第一个被解析的元素生效,后续全部失效 - 不支持 JS 动态设置:
el.autofocus = true或el.setAttribute('autofocus', '')都无效 - 仅适用于可聚焦的表单控件:
<input>(非type="hidden"或disabled)、<textarea></textarea>、<button></button>;<div contenteditable> 等不支持 <h3>DOMContentLoaded 后手动 focus() 必须等 DOM 挂载完成</h3> <p>当 <code>autofocus失效(比如模态框、SPA 路由切换、条件渲染),就得用 JS 主动聚焦。常见错误是过早执行:- 在
DOMContentLoaded之前调用document.getElementById('x').focus()→ 报错Cannot read property 'focus' of null - 在 Vue 的
created或 React 的render阶段调用 → 元素尚未挂载,ref为null - 正确时机:Vue 用
mounted+nextTick,React 用useEffect+ref,原生 JS 用DOMContentLoaded回调 - 加一层防御判断更稳妥:
if (input && document.activeElement !== input) input.focus(),避免覆盖用户已手动聚焦的元素
移动端 Safari 和 Chrome 会拦截非用户手势触发的 focus()
即使 DOM 已就位、JS 也执行了
focus(),iOS Safari 和新版 Android Chrome 仍可能静默失败——光标不出现,document.activeElement还是body。这是因为浏览器策略限制非用户交互(如页面加载、定时器)触发的焦点获取。- 典型现象:桌面端正常,iOS 上无反应,控制台无报错
- 可靠解法:把
focus()绑定到用户事件里,例如<button onclick="input.focus()">开始输入</button> - 若必须程序触发(如弹窗打开后),可用
input.focus({ preventScroll: true })(Chrome 55+/Safari 15.4+ 支持),旧版需 fallback 到用户点击后微任务延迟 - 注意:不要用
requestAnimationFrame替代setTimeout(fn, 0),它执行太晚,常错过焦点激活窗口
focus() 后立即 select() 要防 Safari 异步拦截
想让输入框聚焦后自动选中全部内容,不能直接在
focus事件里调input.select(),尤其在 iOS Safari 上大概率失效(光标定位了,但文字不选中)。- 根本原因:浏览器在某些上下文(如标签页切换后、JS 触发 focus)中会同步拦截
select() - 稳定写法:
input.addEventListener('focus', () => setTimeout(() => input.select(), 0)) - 如果同时用了
autofocus,必须监听focus事件,而不是DOMContentLoaded,否则首次聚焦会漏掉 -
type="number"、type="date"等非文本输入框不支持select(),调用无效
- 在











