blur不冒泡,仅在失焦元素触发;focusout冒泡,可在祖先元素捕获后代失焦。单字段校验用blur,区域级管理用focusout。

blur 和 focusout 都在元素失去焦点时触发,但关键区别在于事件是否向上冒泡——这直接影响你该监听哪个元素、绑定在何处才能捕获到目标行为。
blur:只在目标元素上触发,不传播
blur 是原生失焦事件,严格绑定在获得焦点的那个具体元素上。一旦它失去焦点,事件就只在那里执行,不会传给父级或祖先节点。
- 适用于需要精准控制单个输入框行为的场景,比如校验某个 input 失去焦点时的值
- 不能在父容器上监听子元素的 blur,即使子元素失焦,父元素的 blur 回调也不会运行
- 常见于表单字段级操作,如:
input.addEventListener('blur', validateField)
focusout:支持冒泡,可被祖先捕获
focusout 是 blur 的冒泡版本,行为逻辑一致(都是失焦时触发),但会像 click 一样沿 DOM 向上传播。
- 适合统一管理一组控件的焦点状态,比如整个表单区域失焦时收起提示浮层
- 可在父级 div、form 或 body 上监听,只要任意后代元素失焦,就会触发
- 示例:
form.addEventListener('focusout', () => console.log('表单内某处失焦'))
实际开发中怎么选
判断依据很简单:你要响应的是“这个元素”还是“这个区域里任何一个元素”?
- 只关心当前输入框:用 blur
- 要监听整个模块内任意控件失焦:用 focusout
- 注意兼容性:focusout 在所有现代浏览器和 IE9+ 中都可用,无需 polyfill
- 避免混用:不要对同一元素同时绑定 blur 和 focusout,容易造成重复执行
一个小陷阱提醒
focusout 在某些情况下会比 blur 多触发一次——当焦点从一个元素移到另一个同级元素时,旧元素触发 focusout,新元素也触发 focusout(因为焦点先离开旧元素,再进入新元素)。如果业务逻辑依赖“完全离开本区域”,建议结合 event.relatedTarget 做边界判断。










