perventDefault, stopPropagation, stopImmediatePropagation 三者的区别
event有三种特别容易混淆的方法, 用来阻止默认事件的发生
1. e.preventDefault();
2. e.stopPropagation();
3. e.stopImmediatePropagation();
首先看这三个在MDN上的介绍
preventDefault: 如果当前event.cancelable属性为true, 则取消当前默认的动作, 但不阻止当前事件进一步传播.
stopPropagation: 阻止当前冒泡或者捕获阶段的进一步传播 .
stopImmediatePropagation: 阻止调用相同事件的其他监听器
1. e.preventDefault
下面一个例子, 当点击一个form中的 submit按钮提交表单时, 如果使用了 e.preventDefault , 就可以阻止表单提交
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>表单</title> </head> <body> <form id="myForm" action="www.baidu.com" method="post"> <div> <label for="name">姓名:</label> <input type="text" id="name" /> </div> <div> <label for="mail">电子邮箱:</label> <input type="email" id="mail" /> </div> <div> <label for="msg">消息:</label> <textarea id="msg"></textarea> </div> <div class="button"> <button type="submit">发送你的消息</button> </div> </form> </body> <script type="text/javascript" src="./jquery.js"></script> <script type="text/javascript"> $('#myForm').on('submit', function(e) { e.preventDefault(); // 什么都不会发生 }); </script> </html>
此时使用e.preventDefault就能确保表单不会被提交, 但是他不能用来阻止来自冒泡阶段的submit或者点击事件, 下面两种方法就是为了解决这个问题的
注: 如果 Event 对象的 cancelable 属性是 fasle,那么就没有默认动作,或者不能阻止默认动作。无论哪种情况,调用该方法都没有作用。
2. e.stopPropagation
stopPropagation就是保证当前事件不在进一步冒泡
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>冒泡</title> <style type="text/css"> .box1 { height: 400px; width: 400px; background: #f66; } .box2 { height: 300px; width: 300px; background: #6f6; } .box3 { height: 200px; width: 200px; background: #66f; } </style> </head> <body> <div class="box1"> 1 <div class="box2"> 2 <div class="box3">3</div> </div> </div> </body> <script type="text/javascript" src="./jquery.js"></script> <script type="text/javascript"> $('.box1').on('click', function() { alert('ok'); }) $('.box2').on('click', function(e) { // e.preventDefault(); e.stopPropagation(); // 点击box2不会反应 }) $('.box3').on('click', function(e) { // e.preventDefault(); e.stopPropagation(); // 点击box3不会反应 }) </script> </html>
3. e.stopImmediatePropagation
以上两种方法已经解决了我们在处理事件中90%的问题, 接下来就介绍一种上面两种无法处理的情形
给一个标签添加两个 class, 一个是公共的class: item, 另一个是独有的class: element, 假设这两个class对当前网站的功能都很重要
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div class="container"> <a href="#" class="item element">点击</a> </div> </body> <script type="text/javascript" src="./jquery.js"></script> <script type="text/javascript"> $('.item').on('click', function(e) { console.log('item 被点击了'); }); $('.element').on('click', function(e) { e.preventDefault(); // 此时链接不会跳转 e.stopPropagation(); // 此时事件冒泡被阻止 console.log('element 被点击了'); }); </script> </html>
当我们点击<a>标签时
这个现象会发生是因为item与element在DOM中是被平等对待的,与a标签点击冒泡到父级div不同, 我们点击同时出发了item与element的事件, 此时使用stopPropagation无法阻止这种事件
$('.element').on('click', function(e) { e.preventDefault(); // 此时链接不会跳转 e.stopImmediatePropagation(); // item的点击事件将被阻止 console.log('element 被点击了'); }); $('.item').on('click', function(e) { console.log('item 被点击了'); });