题目:不会冒泡的事件有哪些?

1. 背景知识

在 JavaScript 的 DOM 事件模型中,大部分事件都会按“冒泡阶段”从目标元素向上传递到 document

事件流程

捕获阶段
目标阶段
冒泡阶段
  • 捕获阶段:从 document 一层层向下到目标元素
  • 目标阶段:在目标元素上触发
  • 冒泡阶段:从目标元素向上传递到 document

但有些事件触发后不会进入冒泡阶段,这意味着它们只会在目标元素上触发一次,不会传递给父元素。


2. 常见不会冒泡的事件列表

事件名 说明 备注
focus 元素获取焦点 直接触发在目标元素
blur 元素失去焦点 直接触发在目标元素
focusin 类似 focus,但会冒泡,所以是例外形式
focusout 类似 blur,但会冒泡
load 资源加载完成时触发(img 等) 不冒泡
unload 页面即将被关闭/离开时触发 不冒泡
stop 多媒体播放停止 audio/video 相关
readystatechange document.readyState 改变时触发 主要用于 readystatechange 回调
scroll 元素或窗口滚动 在元素上触发,不冒泡

3. 关键点注意

  • focus / blur 不会冒泡
  • focusin / focusout(对应的事件)是特殊的,它们会冒泡
  • scroll 事件经常被误认为会冒泡,其实不会
  • 这些事件一般用在目标元素上监听,而不是绑定在父元素去代理

4. 代码实验对比

<!DOCTYPE html>
<html>
<head>
    <style>
        .parent {
            width: 300px;
            height: 200px;
            background-color: lightblue;
            padding: 20px;
        }
        .child {
            width: 150px;
            height: 100px;
            background-color: lightcoral;
        }
        .log {
            margin-top: 20px;
            height: 200px;
            overflow-y: auto;
            border: 1px solid #ccc;
            padding: 10px;
        }
    </style>
</head>
<body>
    <div id="parent" class ="parent">
        Parent
        <input type="text" id="child" placeholder="Click me" class="child">
      </div>
    <div id="log" class ="log"></div>
      
      <script>
        const parent = document.getElementById('parent');
        const child = document.getElementById('child');
        const log = document.getElementById('log')
      
        // 父元素监听 focus
        parent.addEventListener('focus', () => {
        log.innerHTML += `Parent focus<br>`;
        });
      
        // 父元素监听 focusin(冒泡的版本)
        parent.addEventListener('focusin', () => {
        log.innerHTML += `Parent focusin<br>`;
        });
      
        // 子元素监听 focus
        child.addEventListener('focus', () => {
        log.innerHTML += `Child focus<br>`;
        });

      </script>
</body>
</html>

在这里插入图片描述

预期结果

  1. 点击输入框 → 输出:
    Child focus
    Parent focusin
    
    Parent focus 没触发,因为 focus 不冒泡;
    focusin 会冒泡到 parent。

5. Mermaid 事件传递对比

focus(不会冒泡)
触发focus
Document
html
body
输入框input
focusin(会冒泡)
触发focusin
触发focusin
触发focusin
Document
html
body
输入框input

6. 使用场景建议

  • 不会冒泡的事件
    • 必须绑定在目标元素本身
      例如:
      input.addEventListener('focus', handler);
      
  • 会冒泡的同类事件
    • 可以利用事件代理,提高代码效率
      例如:
      parent.addEventListener('focusin', handler);
      

7. 刷题总结(答题模板)

在 JS 中,大多数事件会冒泡,但以下常见事件不会冒泡focusblurloadunloadstopreadystatechangescroll
特别地,focus / blur 不会冒泡,但它们的对应版本 focusin / focusout 会冒泡。
实际开发中,如果希望用代理监听焦点变化,可以用 focusinfocusout 代替。
个人理解:不会冒泡的你要监听触发的子元素本身,会冒泡的你只需要监听父元素就可以得到子元素是否触发的消息。


更多推荐