focus/blur是监听元素获/失焦点最直接可靠的方式,但不冒泡且仅对可聚焦元素生效;需用tabindex使div等元素可聚焦,禁用元素或tabindex="-1"会阻断事件,推荐addeventlistener绑定,focusin/focusout可用于事件委托。

focus 和 blur 是监听元素是否获得/失去焦点最直接、最可靠的方式,但它们不冒泡,且只对可聚焦元素生效——这点不处理好,事件根本不会触发。
哪些元素能触发 focus/blur?
只有「可聚焦元素」才能自然触发这两个事件。常见支持的有:input、textarea、select、button、带 href 的 a 标签、iframe;而普通 div、span 默认不行。
让 div 支持聚焦,必须显式加 tabindex:
<div tabindex="0">我能被 Tab 进入,也能点它触发 focus</div>
注意以下情况会彻底阻断事件:
-
disabled状态的表单元素(如<input disabled>)不会触发focus或blur -
tabindex="-1"允许 JS 调用.focus(),但不能通过 Tab 键进入,也不影响可聚焦性判断 -
contenteditable="true"的元素也默认可聚焦
addEventListener 是唯一推荐的绑定方式
别用 onfocus/onblur 属性赋值或内联写法,它们会覆盖已有逻辑、无法传参、难解绑,还容易在组件卸载后引发内存泄漏。
正确做法是统一用 addEventListener:
const input = document.getElementById('email');
input.addEventListener('focus', () => {
input.classList.add('focused');
});
input.addEventListener('blur', () => {
if (!input.value.trim()) {
input.classList.add('error');
}
});
关键细节:
- 两个事件都不冒泡,所以不能在父容器上监听子
input的focus - 若需委托(比如整个
form统一处理所有输入框),改用focusin/focusout—— 它们冒泡,且行为兼容性好(IE9+、现代浏览器全支持) - 不要在
focus回调里调用input.focus(),可能造成焦点循环或屏幕阅读器异常
blur 事件常被误用于“提交校验”,但它不是“用户完成输入”的信号
blur 只表示焦点离开,不代表用户已填完、更不代表要提交。例如用户从邮箱框切到密码框,邮箱框就 blur 了,但此时立刻校验邮箱格式,体验反而突兀。
更合理的组合策略:
-
focus:清空错误提示、显示帮助文案、启用实时校验(如长度提示) -
blur:做轻量格式检查(如邮箱基础结构)、标记“该字段已访问过” - 真正提交前再跑完整校验,避免过早报错
另外,移动端键盘收起不等于 blur——某些 WebView 中点击软键盘「完成」按钮,blur 可能延迟或丢失,建议加一层防抖或结合 input 事件兜底。
自动聚焦要注意无障碍和时机
页面加载后想默认聚焦某个输入框,优先用 HTML 的 autofocus 属性:
<input type="text" autofocus placeholder="搜索...">
它由浏览器统一管控,兼顾屏幕阅读器和移动设备行为。JS 方式 input.focus() 必须确保 DOM 已就绪,且避开以下陷阱:
- 在
DOMContentLoaded之前调用 → 报错Cannot read property 'focus' of null - 在模态框未渲染完成时调用 → 焦点设置失败(尤其 Vue/React 动态组件)
- 在非用户手势(如页面加载)中强制聚焦 → 屏幕阅读器可能跳过前面内容,违反 WCAG
真正复杂的是多步骤表单或动态插入的输入框:焦点管理必须和状态同步,否则 JS 中的 isFocused 变量和真实 DOM 焦点会脱节——这是最容易被忽略、也最难调试的问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











