input.focus()不生效是因为未满足浏览器强制的四个前提:目标元素非当前焦点、未被隐藏、在用户手势上下文中调用、已正确插入dom且tabindex设置合理。

input.focus() 不生效,不是代码写错了,而是你没满足浏览器强制执行的四个前提条件。
调用 focus() 无效的四个硬性前提
浏览器对 focus() 的调用有明确限制,任意一条不满足都会静默失败:
-
document.activeElement已是目标元素 → 白调,应先判断:if (input && document.activeElement !== input) input.focus() - 元素被
display: none或visibility: hidden包裹 →getComputedStyle(input).display !== 'none'必须为真 - 在非用户手势上下文中调用(如 AJAX 回调、
setTimeout)→ iOS Safari 和部分安卓 WebView 会拦截,不报错也不弹键盘 - 元素未插入 DOM,或
tabindex设置错误 → 原生input默认可聚焦;若用div模拟输入框,必须设tabindex="0",不能是-1
表单提交或 reset 后焦点自动丢失是标准行为
这不是 bug,是规范要求。但你可以主动恢复:
- 对
submit:在event.preventDefault()后手动聚焦,避免页面跳转干扰 - 对
reset:监听reset事件,在回调里加setTimeout(() => input.focus(), 0)—— 因为重置操作同步完成,但 DOM 更新可能有微小延迟 - 用第三方库(如
react-hook-form)时,查文档确认是否有onReset钩子,别直接操作 DOM
移动端软键盘不弹出或输完就失焦
iOS Safari 对软键盘触发极其保守,单纯 focus() 不保证唤起键盘:
- 必须包裹在用户手势中:比如按钮的
onclick、touchend或keydown(Enter 键)回调内调用input.focus() - 输完一个字符就失焦?检查是否绑了
onchange或oninput并在其中执行了 DOM 更新(如重渲染父组件),导致input被销毁重建 - 键盘弹出后页面滚动?加参数避免:
input.focus({ preventScroll: true })—— 注意 Safari 15.4+ 才支持该选项 - 动态插入的
input(如模态框内):不要依赖autofocus,改用shown.bs.modal(Bootstrap)或useEffect(React)等安全钩子
blur 事件里试图阻止失焦基本无效
event.preventDefault() 在 blur 中不起作用,这是浏览器强制行为。所谓“阻止失焦”本质是失焦后立刻再聚焦回来,但有风险:
- 会造成视觉闪烁,尤其在快速切换 tab 或点击其他
input时 - 某些场景(如屏幕阅读器、键盘导航)下破坏可访问性
- 若在
blur中异步聚焦(如setTimeout),可能被后续用户操作覆盖
真正容易被忽略的是:**焦点管理不是“让某个元素获得焦点”,而是确保它在正确时机、正确上下文、正确可访问性约束下获得焦点——漏掉任一环节,行为就会退化成不可预测的“偶尔有效”。**
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











