focus/blur不支持事件冒泡,无法委托;focusin/focusout是其冒泡版本,可绑定到父容器实现委托,通过event.target识别具体元素并配合matches()筛选目标。

focus 和 blur 不支持事件冒泡,无法直接用于事件委托;focusin 和 focusout 是它们的冒泡版本,正好可以替代实现焦点事件的委托。
为什么 focus/blur 不能委托,而 focusin/focusout 可以
focus 和 blur 是非冒泡事件,触发后不会向父元素传播,所以给父容器绑定 focus/blur 无效。focusin 和 focusout 是 W3C 标准定义的冒泡版等价事件(focusin ≈ focus + 冒泡,focusout ≈ blur + 冒泡),因此能被父级捕获。
基本用法:用 focusin/focusout 替代并委托到父容器
将事件监听绑定在共同祖先(如 form、div#form-container),通过 event.target 判断具体聚焦/失焦的子元素:
- 用 addEventListener('focusin', handler) 替代 focus
- 用 addEventListener('focusout', handler) 替代 blur
- handler 中通过 event.target 获取实际获得/失去焦点的元素
- 可结合 matches() 筛选目标(如 input[type="text"], textarea)
示例:为表单内所有文本类输入框统一处理聚焦逻辑
HTML:
JS:
const form = document.getElementById('myForm');form.addEventListener('focusin', e => {
if (e.target.matches('input[type="text"], input[type="email"], textarea')) {
e.target.classList.add('focused');
console.log('获得焦点:', e.target.name);
}
});
form.addEventListener('focusout', e => {
if (e.target.matches('input, textarea')) {
e.target.classList.remove('focused');
console.log('失去焦点:', e.target.name);
}
});
注意事项
- focusin/focusout 在所有现代浏览器中均受支持(包括 IE8+),兼容性良好
- 它们不会在 disabled 元素上触发,行为与 focus/blur 一致
- 注意 focusout 会在子元素间切换焦点时也触发(例如从 input 切到同一父容器下的 button),如需排除可检查 event.relatedTarget 是否仍在委托容器内
- 不要混用:避免同时监听 focus/blur 和 focusin/focusout,可能造成重复执行


















