event事件对象有三种易混淆的方法,本文讲述他们之间的区别:
- Event.preventDefault()
- Event.stopPropagation()
- Event.stopImmediatePropagation()
综述
首先,我们看看他们在MDN上的介绍:
- preventDefault: 如果当前event.cancelable属性为true,则取消的当前事件的默认动作,但不阻止当前事件的进一步传播
- stopPropagation: 阻止当前冒泡或捕获阶段的进一步传播
- stopImmediatePropagation: 阻止调用相同事件的其他监听器
Event.preventDefault
我们来看一个代码示例,当点击一个form中的submit按钮时会将form提交处理,此时如果使用Event.preventDefault,就可以在点击submit按钮时避免表格提交。
<form id="myForm" action="/my-handling-form-page" 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>
$('#myForm').on('submit', function(e) {
e.preventDefault(); // 什么都不会发生
});
Event.preventDefault能确保表格不会被提交,但他不能阻止来自冒泡阶段的submit或点击事件,其他两种方法就是解决这个问题的。
Event.stopPropagation
stopPropagation 保证当前事件不再进一步冒泡,通过以下代码示例说明:
<div class="container">
<a href="#" class="element">点击我!</a>
</div>
$('.container').on('click', function(e) {
console.log('container 被点击了');
});
$('.element').on('click', function(e) {
e.preventDefault(); // 此时链接不会跳转
console.log('element 被点击了');
});
此时点击链接,console会显示:
"element 被点击了"
"container 被点击了"
这时如果添加Event.stopPropagation:
$('.container').on('click', function(e) {
console.log('container 被点击了');
});
$('.element').on('click', function(e) {
e.preventDefault(); // 此时链接不会跳转
e.stopPropagation(); // 此时事件冒泡被阻止
console.log('element 被点击了');
});
再次点击链接,会看到:
"element 被点击了"
Event.stopImmediatePropagation
以上两种方法已经可以解决我们在事件处理中90%的问题,接下来介绍一种无法解决情形。
同样是使用上面的示例,但这次我们给<a/>添加2个class,一个是被所有<a/>共享的class: item,另一个是独有的class: element,假设这两个class对当前网站的功能很重要。
<div class="container">
<a href="#" class="item element">Click Me!</a>
</div>
我们首先使用之前提到的Event.stopPropagation
$('.element').on('click', function(e) {
e.preventDefault(); // 此时链接不会跳转
e.stopPropagation(); // 此时事件冒泡被阻止
console.log('element 被点击了');
});
$('.item').on('click', function(e) {
console.log('item 被点击了');
});
当我们点击<a/>时,将会显示:
"item 被点击了"
"element 被点击了"
这个现象会发生是因为item与element在DOM中是被平等对待的,与之前<a/>被点击然后冒泡到父级div不同,这次我们点击同时触发了item与element的事件,此时使用stopPropagation无法阻止这种事件。
stopImmediatePropagation登场~
他可以阻止事件冒泡并且阻止相同事件的其他侦听器被调用。
$('.element').on('click', function(e) {
e.preventDefault(); // 此时链接不会跳转
e.stopImmediatePropagation(); // item的点击事件将被阻止
console.log('element 被点击了');
});
$('.item').on('click', function(e) {
console.log('item 被点击了');
});
这里我们要注意的一点是:stopImmediatePropagation的代码要尽量放到其他同级竞争事件代码的上面,如上面的例子中,为了使stopImmediatePropagation起作用,我们将element的事件监听代码放到了item之前!
运行最后一例中的代码,将只会看到:
"element 被点击了"
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。