冒泡和捕获是 JS 中事件的两种传递方式。在 冒泡 中,内部元素的事件会先被触发,然后再触发外部元素。
在 捕获 中,外部元素的事件会先被触发,然后才会触发内部元素的事件。
# 冒泡和捕获
参考以下代码:
1 | <div id="level1"> |
1 | window.onload = () => { |
在这个例子中,id 为 level3 的元素在 level2 元素内部,而 level2 元素又在 level1 的元素内部,因此点击了 level3 的元素,这个点击事件也会传递给 level2 和 level1 的元素,这时会输出 3 2 1
。这就是冒泡。
而为了触发 捕获,则需要将 addEventListener 的第三个参数设置为 true(默认是 false),这时就会输出 1 2 3
。
# 阻止事件传递
为了在点击 level3 元素时,不发生 level1 和 level2 元素的点击事件,就需要对事件传递进行阻止。
w3c 的方法是 e.stopPropagation()
,也是目前最常使用的方法(兼容性为除了 IE9 以下,Edge12 以下的所有浏览器),IE 则是使用 e.cancelBubble = true
(IE6 7 8)
stopPropagation
是事件对象(Event)的一个方法,作用是阻止目标元素的冒泡事件,但不会阻止默认行为。
# 取消默认事件
w3c 的方法是 e.preventDefault()
,IE 则是使用 e.returnValue = false
;
preventDefault
它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。既然是说默认行为,当然是元素必须有默认行为才能被取消。如链接 <a>
,提交按钮 <input type=”submit”>
等。当 Event 对象的 cancelable 为 false 时,表示没有默认行为,这时即使有默认行为,调用 preventDefault 也是不会起作用的。
比如,用来禁止选择网页上的文字:
1 | document.addEventListener('selectstart', function(e){ |
# return false
return false
等效于同时调用 e.preventDefault()
和 e.stopPropagation()
return false
除了阻止默认行为之外,还会阻止事件冒泡。
在 jQuery 的源码中,有如下代码:
1 | if (ret === false) { |