js中不会冒泡的事件有哪些?
不会冒泡的事件有哪些?
核心规则:大多数原生DOM事件会冒泡,但凡标记了bubbles:false的就不会。
一、最常被踩坑的几个
1.focus/blur-不冒泡
// ❌ blur/focus 不冒泡,这样可能收不到 parent.addEventListener('blur', handler); // ✅ 方案A:用冒泡版(部分浏览器支持) parent.addEventListener('focusin', handler); parent.addEventListener('focusout', handler); // ✅ 方案B:捕获阶段监听(最通用、最可靠) parent.addEventListener('focus', handler, true); parent.addEventListener('blur', handler, true);2.mouseenter/mouseleave-刻意不冒泡
这就是它们存在的原因-跟mouseover/mouseout做区分:
| 事件 | 冒泡 | 穿过子元素时会重复触发? |
| mouseover/mouseout | 冒泡 | 会(因为子元素边界也算) |
| mouseenter/mouseleave | 不冒泡 | 不会(只在进出“当前元素整体”时各一次) |
el.addEventListener('mouseenter', () => console.log('enter')); // OK // 挂到父元素上等它冒泡上来 → 永远不会触发3.scroll-不冒泡
// ❌ 这样通常没用(scroll 不冒泡) parent.addEventListener('scroll', handler); // ✅ 捕获阶段才能拦到子元素的 scroll parent.addEventListener('scroll', handler, { capture: true });二、完整归类清单
焦点类(Focus Events)
| 事件 | 冒泡? | 备注 |
| focus | 不冒泡 | |
| blur | 不冒泡 | |
| focusin | 冒泡 | IE起源,规范仍保留但部分环境有差异 |
| focusout | 冒泡 | 同上 |
鼠标指针进入/离开类
| 事件 | 冒泡? |
| mouseenter | × |
| mouseleave | × |
| pointerenter | × |
| pointerleave | × |
资源加载/页面生命周期类
这些事件的触发源本身就不在常规“冒泡链”里:
| 事件 | 冒泡? | 触发对象 |
| load(img/iframe/script等元素级) | × | 特定元素 |
| error(资源加载失败) | × | img/script/link等 |
| unload | × | window |
| beforeunload | × | window |
| readystatechange | × | document/xhr |
滚动/尺寸类
| 事件 | 冒泡? |
| scroll | ×(bubbles:false) |
| resize | N/A(只存在于window) |
表单验证类
| 事件 | 冒泡? |
| invalid | ×不冒泡 |
// invalid 不会冒泡到 form 上通过冒泡捕获 form.addEventListener('invalid', handler); // ❌ 大概率漏掉 form.addEventListener('invalid', handler, true); // ✅ 捕获阶段三、怎么自己验证?
任何事件都可以秒查:
const e = new MouseEvent('click'); console.log(e.bubbles); // true const f = new FocusEvent('focus'); console.log(f.bubbles); // false // 对已有事件类型查原形 console.log(Event.prototype.__proto__.constructor === UIEvent); // 辅助判断类型 // 更直接:查 MDN 或规范,或者: document.createElement('div').onfocus; // 看看它是什么事件或直接在控制台看规范属性:
// 创建一个真实 event 看它的 bubbles/composed const evt = new Event('yourEventType', { bubbles: true }); // 但注意:内置事件要这样看: const scrollEvt = new UIEvent('scroll'); Object.getOwnPropertyNames(scrollEvt);"状态通知型"事件多半不冒泡,"交互动作型"事件多半冒泡。
焦点是状态 →
focus/blur不冒泡进出一个区域是边界语义 →
mouseenter/mouseleave不冒泡滚动是元素自身状态变化 →
scroll不冒泡点击是明确的用户动作 →
click冒泡 ✅
