autofocus在vue/react中无效,因仅在html解析时生效;js动态插入dom时需手动focus(),且必须满足挂载、可见、可聚焦三条件,并在用户手势上下文中调用,推荐requestanimationframe+保护逻辑。

autofocus在Vue/React里根本不会触发
它只在浏览器解析原始HTML字符串时扫描一次,Vue的<input autofocus>或React的<input autofocus>都是JS运行时插入DOM,此时autofocus早已“过期”。控制台不报错,但document.activeElement永远不是那个输入框。
手动focus()必须等三件事同时满足
不能一挂载就调input.focus(),否则静默失败。得确认:
-
input.offsetParent !== null(已挂载且未被display: none隐藏) getComputedStyle(input).visibility !== 'hidden'input.tabIndex >= 0 && !input.disabled && !input.hasAttribute('inert')
推荐统一用requestAnimationFrame(() => input.focus()),比setTimeout(() => ..., 0)更可靠,能避开CSS transition未结束或渲染未完成的时机。
iOS Safari要求focus()必须在用户手势上下文中调用
单纯靠useEffect(() => ref.current?.focus(), [])或onMounted(() => inputRef.value?.focus())在iOS上基本无效。必须把focus()放在click、touchstart等事件回调里立即执行:
button.addEventListener('click', () => {
input.focus();
});
模态框由按钮打开?就在该按钮的点击事件里聚焦;路由跳转后想聚焦?监听popstate或框架的afterEach钩子,并确认操作源自用户导航(如history.pushState是用户点击触发的)。
多个autofocus共存时焦点会乱跳
HTML规范只要求第一个被解析到的autofocus生效,而“第一个”取决于源码顺序,不是渲染顺序。更危险的是:
- 初始HTML里有个隐藏搜索框带
autofocus,异步加载的登录表单也带,后者永远抢不到 - SSR后hydrate,两个
autofocus同时存在,但只有SSR输出中那个生效
解决办法很简单:删掉所有autofocus属性,统一用JS控制,且调用前加保护逻辑:if (input && document.activeElement !== input) { input.focus(); }。
真正要实现“挂载即聚焦”,autofocus只是个快捷但脆弱的开关;focus()才是可控动作。最容易被忽略的不是“怎么写”,而是“什么时候调、要不要调”——尤其当元素被v-if、display: none或服务端渲染干扰时。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











