事件流:阻止事件冒泡、阻止事件捕获preventDefault()、stopPropagation()、return false 之间的区别

本文介绍W3C中事件发生的三个阶段,即捕获、目标和冒泡阶段,阐述冒泡型和捕获型事件的触发顺序。还说明了阻止事件发生的方法,包括阻止冒泡和捕获的不同方式。最后探讨事件函数执行先后顺序,得出捕获阶段先执行,其次目标阶段,最后冒泡阶段,目标阶段先注册先执行的结论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考文章:https://www.jb51.net/article/94394.htm


W3C 中定义事件的发生经历三个阶段:

捕获阶段(capturing)、目标阶段(targetin)、冒泡阶段(bubbling)

  • 冒泡型事件:当你使用事件冒泡时,子级元素先触发,父级元素后触发
  • 捕获型事件:当你使用事件捕获时,父级元素先触发,子级元素后触发
  • DOM事件流:同时支持两种事件模型:捕获型事件和冒泡型事件

阻止事件发生的方法:

  • 阻止冒泡:在W3c中,使用 stopPropagation() 方法;在IE下设置 cancelBubble = true
  • 阻止捕获:阻止事件的默认行为,例如 click - <a> 后的跳转。在W3c中,使用 preventDefault() 方法,在 IE 下设置 window.event.returnValue = false

再谈事件函数执行先后顺序:

利用 addEventListener() 在元素上绑定多个事件,且设置不同的事件流。也就是说,先后绑定两个click 事件,一个设置事件冒泡,一个设置事件捕获

我们在outC上触发onclick事件(这个是目标对象),如果我们在outC上同时绑定捕获阶段/冒泡阶段事件处理函数会怎么样呢?

<script>
 
 window.onload = function(){
        var outA = document.getElementById("outA");
        var outB = document.getElementById("outB");
        var outC = document.getElementById("outC");

        // 目标(自身触发事件,是冒泡还是捕获无所谓)
        outC.addEventListener('click',function(){console.log("target2");},true);
        outC.addEventListener('click',function(){alert("target1");},true);

        // 事件冒泡
        outB.addEventListener('click',function(){alert("bubble2");},false);
        outA.addEventListener('click',function(){alert("bubble1");},false);

        // 事件捕获
        outB.addEventListener('click',function(){alert("capture2");},true);
        outA.addEventListener('click',function(){alert("capture1");},true);
  
</script>
 
<body>
 <div id="outA" style="width:400px; height:400px; background:#CDC9C9;position:relative;">
 <div id="outB" style="height:200; background:#0000ff;top:100px;position:relative;">
  <div id="outC" style="height:100px; background:#FFB90F;top:50px;position:relative;"></div> 
 </div>
 </div>
</body>

点击outC的时候,打印顺序是:capture1-->capture2-->target2-->target1-->bubble2-->bubble1。

捕获事件最后才绑定 ,但是最先执行了;然后是目标阶段的事件;最后是冒泡事件。

捕获事件 --> 目标阶段 --> 冒泡事件

由于outC是我们触发事件的目标对象,在outC上注册的事件处理函数,属于DOM事件流中的目标阶段。目标阶段函数的执行顺序:先注册的先执行,后注册的后执行。这就是上面我们说的,在目标对象上绑定的函数是采用捕获,还是采用冒泡,都没有什么关系,因为冒泡和捕获只是对父元素上的函数执行顺序有影响,对自己没有什么影响。如果不信,可以将下面的代码放进去验证。

// 目标(自身触发事件,是冒泡还是捕获无所谓)
    outC.addEventListener('click',function(){console.log("target1");},false);
    outC.addEventListener('click',function(){console.log("target2");},true);
    outC.addEventListener('click',function(){console.log("target3");},true);
    outC.addEventListener('click',function(){console.log("target4");},false);

至此我们可以给出事件函数执行顺序的结论了:捕获阶段的处理函数最先执行,其次是目标阶段的处理函数,最后是冒泡阶段的处理函数。目标阶段的处理函数,先注册的先执行,后注册的后执行。

 

 

 

 

<think>我们讨论的是JavaScript中的preventDefault方法。这个方法用于阻止事件的默认行为。 例如,当点击一个链接时,默认行为是导航到链接的URL;当提交表单时,默认行为是重新加载页面或导航到表单的action属性指定的URL。使用preventDefault可以阻止这些默认行为的发生。 以下是一个使用preventDefault的简单示例。我们将创建一个链接,当点击它时,阻止它跳转到目标URL,而是执行一些其他操作(比如在控制台打印一条消息)。 代码示例: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>preventDefault Example</title> </head> <body> <a href="https://www.example.com" id="myLink">Click me</a> <script> // 获取链接元素 const link = document.getElementById('myLink'); // 添加点击事件监听器 link.addEventListener('click', function(event) { // 阻止默认行为(即阻止跳转到href指定的URL) event.preventDefault(); console.log('Link clicked, but default behavior prevented.'); // 这里可以添加其他自定义行为 }); </script> </body> </html> ``` 解释: 1. 我们在HTML中创建了一个指向"https://www.example.com"的链接。 2. 使用JavaScript获取该链接的DOM元素。 3. 给这个链接添加了一个点击事件监听器。当链接被点击时,监听器函数会被调用,并传入一个事件对象(通常命名为`event`或`e`)。 4. 在监听器函数中,我们调用了事件对象的`preventDefault()`方法,这会阻止链接的默认行为(即不会跳转到指定的URL)。 5. 然后我们在控制台打印一条消息,表示链接被点击但默认行为被阻止了。 另一个常见的例子是阻止表单的默认提交行为,以便使用AJAX提交表单数据。 示例:阻止表单提交的默认行为 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Prevent Form Default</title> </head> <body> <form id="myForm"> <input type="text" name="username" placeholder="Username"> <button type="submit">Submit</button> </form> <script> const form = document.getElementById('myForm'); form.addEventListener('submit', function(event) { event.preventDefault(); // 阻止表单的默认提交行为(即页面刷新或跳转) console.log('Form submitted, but default behavior prevented.'); // 这里可以获取表单数据并发送AJAX请求 // 例如: const formData = new FormData(this); // ... 使用fetch或XMLHttpRequest发送数据 }); </script> </body> </html> ``` 解释: 1. 我们有一个简单的表单,包含一个文本输入框和一个提交按钮。 2. 给表单添加了`submit`事件监听器。 3. 在监听器函数中,调用`event.preventDefault()`阻止表单的默认提交行为(即页面刷新或跳转)。 4. 然后可以在这里处理表单数据,比如使用AJAX发送数据到服务器。 注意事项: - `preventDefault()`方法只会阻止事件的默认行为,而不会阻止事件继续传播(即冒泡捕获阶段)。如果需要停止事件传播,可以使用`event.stopPropagation()`。 - 在事件监听器中,如果希望既阻止默认行为又停止事件传播,可以同时调用这两个方法。但要注意,停止传播可能会影响其他监听器的执行。 现在,根据要求,提出相关问题: §§相关问题§§: 1. 在JavaScript中,preventDefaultstopPropagation有什么区别? 2. 如何阻止事件冒泡?请给出代码示例。 3. 在React中如何阻止事件的默认行为? 4. 如果在一个事件监听器中,我使用了return false,它和preventDefault()有什么不同?</think>### `preventDefault` 方法详解 `preventDefault()` 是 JavaScript 事件对象的方法,用于阻止浏览器对事件的**默认行为**。例如: - 阻止 `<a>` 标签的跳转 - 阻止表单提交时的页面刷新 - 阻止右键菜单弹出 - 阻止空格键滚动页面 #### 使用示例 ```html <!DOCTYPE html> <html> <body> <!-- 示例1:阻止链接跳转 --> <a href="https://example.com" id="myLink">点击我(不会跳转)</a> <!-- 示例2:阻止表单提交 --> <form id="myForm"> <input type="text" required> <button type="submit">提交(不会刷新)</button> </form> <!-- 示例3:阻止空格键滚动 --> <div id="logger" style="margin-top: 200vh; color: red;"></div> <script> // 1. 阻止链接默认跳转 document.getElementById('myLink').addEventListener('click', (e) => { e.preventDefault(); // 核心代码 alert('已阻止跳转到 example.com'); }); // 2. 阻止表单提交刷新页面 document.getElementById('myForm').addEventListener('submit', (e) => { e.preventDefault(); // 核心代码 alert('表单已提交(但页面未刷新)'); }); // 3. 阻止空格键滚动页面 window.addEventListener('keydown', (e) => { if (e.code === 'Space') { e.preventDefault(); // 核心代码 document.getElementById('logger').innerText = `阻止了空格键默认滚动行为 (${new Date().toLocaleTimeString()})`; } }); </script> </body> </html> ``` #### 关键特性: 1. **作用对象**:必须是可取消的事件(通过 `e.cancelable` 属性检查) 2. **执行阶段**:需在事件传播的**捕获阶段或冒泡阶段**调用(不能在事件派发后调用) 3. **组合使用**: ```javascript element.addEventListener('click', (e) => { e.preventDefault(); // 阻止默认行为 e.stopPropagation(); // 阻止事件冒泡(可选) // 自定义逻辑... }); ``` #### 与 `return false` 的区别: | 方式 | 作用范围 | 推荐度 | |--------------------|------------------------|--------| | `e.preventDefault()` | 仅阻止默认行为 | ✅ 推荐 | | `return false` | 阻止默认行为+停止冒泡 | ⚠️ 仅适用于 jQuery 和 on-event 属性 | > 在现代 JavaScript 中,始终优先使用 `preventDefault()`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值