JavaScript 不会冒泡的事件有哪些?

作者:Administrator 发布时间: 2026-05-13 阅读量:4 评论数:0

不会冒泡的事件主要有以下几类

1. 焦点相关事件

  • focus - 元素获得焦点

  • blur - 元素失去焦点

  • focusin - 元素获得焦点(会冒泡)

  • focusout - 元素失去焦点(会冒泡)

// focus 和 blur 不会冒泡
document.getElementById('input').addEventListener('focus', (e) => {
  console.log('focus 事件不会冒泡到父元素');
}, false);  // 捕获阶段监听

// 使用 focusin 替代(会冒泡)
document.getElementById('parent').addEventListener('focusin', (e) => {
  console.log('focusin 事件会冒泡');
});

2. 鼠标进入/离开事件

  • mouseenter - 鼠标进入元素

  • mouseleave - 鼠标离开元素

  • mouseover - 鼠标进入元素(会冒泡)

  • mouseout - 鼠标离开元素(会冒泡)


复制代码
<div id="outer" style="padding: 50px; background: lightblue;">
  <div id="inner" style="padding: 30px; background: lightcoral;"></div>
</div>

<script>
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');

// mouseenter/mouseleave 不会冒泡
outer.addEventListener('mouseenter', () => console.log('outer: mouseenter'));
outer.addEventListener('mouseleave', () => console.log('outer: mouseleave'));

// mouseover/mouseout 会冒泡
outer.addEventListener('mouseover', () => console.log('outer: mouseover - 会冒泡'));
outer.addEventListener('mouseout', () => console.log('outer: mouseout - 会冒泡'));
</script>

3. 加载相关事件

  • load - 资源加载完成

  • unload - 文档卸载

  • beforeunload - 文档即将卸载

  • abort - 资源加载中断

  • error - 资源加载失败

// load 事件不会冒泡
window.addEventListener('load', () => {
  console.log('页面加载完成');
});

// 图片加载事件
const img = new Image();
img.addEventListener('load', () => {
  console.log('图片加载完成,但事件不会冒泡');
});

4. UI 事件

  • scroll - 元素滚动

  • resize - 窗口大小改变

// scroll 事件不会冒泡
window.addEventListener('scroll', () => {
  console.log('滚动事件,不会冒泡');
});

// 但可以在捕获阶段监听
document.addEventListener('scroll', () => {
  console.log('在捕获阶段监听 scroll');
}, true);

5. 媒体事件

  • play - 媒体开始播放

  • pause - 媒体暂停

  • ended - 媒体播放结束

  • volumechange - 音量改变

const video = document.querySelector('video');
video.addEventListener('play', () => {
  console.log('视频播放,事件不会冒泡');
});

6. 其他不会冒泡的事件

  • DOMNodeInserted - 节点插入(已废弃)

  • DOMNodeRemoved - 节点移除(已废弃)

  • DOMAttrModified - 属性修改(已废弃)

处理不会冒泡的事件

方法1:使用捕获阶段

// 在捕获阶段监听 focus 事件
document.addEventListener('focus', (e) => {
  console.log('捕获阶段监听到 focus:', e.target);
}, true);  // true 表示捕获阶段

方法2:使用会冒泡的替代事件

// 使用 focusin 替代 focus
document.addEventListener('focusin', (e) => {
  console.log('focusin 会冒泡:', e.target);
});

// 使用 mouseover 替代 mouseenter
document.addEventListener('mouseover', (e) => {
  console.log('mouseover 会冒泡:', e.target);
});

方法3:事件委托的替代方案

// 对于不会冒泡的事件,需要直接为每个元素绑定
const inputs = document.querySelectorAll('input');
inputs.forEach(input => {
  input.addEventListener('focus', handleFocus);
});

// 或者使用会冒泡的 focusin
document.addEventListener('focusin', (e) => {
  if (e.target.matches('input')) {
    handleFocus(e);
  }
});

检测事件是否会冒泡

function doesEventBubble(eventName) {
  const element = document.createElement('div');
  let bubbles = false;
  
  element.addEventListener(eventName, (e) => {
    bubbles = e.bubbles;
  });
  
  // 触发事件
  const event = new Event(eventName);
  element.dispatchEvent(event);
  
  return bubbles;
}

console.log('focus 冒泡吗?', doesEventBubble('focus'));  // false
console.log('click 冒泡吗?', doesEventBubble('click'));  // true
console.log('mouseenter 冒泡吗?', doesEventBubble('mouseenter')); // false

记忆技巧

Mnemonic: "FBM LUR"

  • Focus/Blur

  • Browser (load/unload/resize)

  • Mouseenter/Mouseleave

  • Load/Unload

  • UI events (scroll/resize)

  • Resource/media events

实际应用建议

  1. 表单验证:使用 focusin 而不是 focus 进行事件委托

  2. 鼠标悬停效果:使用 mouseover/mouseout 而不是 mouseenter/mouseleave 进行事件委托

  3. 性能优化:对于不会冒泡的事件,考虑是否需要为大量元素单独绑定

评论