事件在web
開發(fā)中太常見了耿导。
web
瀏覽器在主線程主隊列任務執(zhí)行完成之后声怔。
基本就進入到了到了eventLoop
等待事件驅動的環(huán)節(jié)了。
1. 事件模型
W3C 標準定義了兩種事件模型.
- 事件捕獲
- 事件冒泡
除了 IE9 以及以下版本,現在主流的瀏覽器都支持這兩種事件模型.
事件捕獲:
在由嵌套層次(非視覺上)的元素結構里.
當有事件發(fā)生時,事件總是被最外層的元素捕獲到,并依次往內部傳遞.
傳遞方向是:從外到內.
<div class="parent">
<div class="child"></div>
</div>
let parent = document.querySelector('.parent'),
child = document.querySelector('.child')
parent.addEventListener('click', function () {
console.log('parent event capture')
}, true)
child.addEventListener('click', function () {
console.log('child event capture')
}, true)
結果:
parent event capture
child event capture
事件冒泡
在包含有嵌套關系層級結構的元素里.
當有事件發(fā)生時,事件總是先被點擊的那個元素獲取到.
然后依次往外傳遞.
事件傳遞方向:從內到外.
<div class="parent">
<div class="child"></div>
</div>
parent.addEventListener('click', function () {
console.log('parent event bubble')
}, false)
child.addEventListener('click', function () {
console.log('child event bubble')
}, false)
結果:
child event bubble
parent event bubble
自己提問一:如果同一個元素同時綁定事件冒泡和事件捕獲兩種方式呢?
先綁定事件冒泡,在綁定事件捕獲.
let bubble_capture = document.querySelector('.bubble-capture')
bubble_capture.addEventListener('click', function () {
console.log('事件冒泡')
}, false)
bubble_capture.addEventListener('click', function () {
console.log('事件捕獲')
}, true)
執(zhí)行結果:
事件冒泡
事件捕獲
先綁定事件捕獲,在綁定事件冒泡.
bubble_capture.addEventListener('click', function () {
console.log('事件捕獲')
}, true)
bubble_capture.addEventListener('click', function () {
console.log('事件冒泡')
}, false)
執(zhí)行結果:
事件捕獲
事件冒泡
先執(zhí)行事件捕獲,在執(zhí)行事件冒泡.
結論:
單個元素同時綁定兩種事件模型.先綁定的模型先執(zhí)行,后綁定的模型后執(zhí)行.
自己提問二:如果帶有嵌套關系的多個元素同時綁定事件冒泡和事件捕獲兩種方式呢?
WEB頁面中,有三個嵌套的DIV元素.
<div class="parent">
<div class="child">
<div class="box"></div>
</div>
</div>
三個有嵌套關系的DIV
let parent = document.querySelector('.parent'),
child = document.querySelector('.child'),
box = document.querySelector('.box')
// 事件捕獲.
parent.addEventListener('click', function () {
console.log('parent event capture')
}, true)
child.addEventListener('click', function () {
console.log('child event capture')
}, true)
box.addEventListener('click', function () {
console.log('box event capture')
}, true)
// 事件冒泡
parent.addEventListener('click', function () {
console.log('parent event bubble')
}, false)
child.addEventListener('click', function () {
console.log('child event bubble')
}, false)
box.addEventListener('click', function () {
console.log('box event bubble')
}, false)
點擊最里面的藍色的DIV.(box)
輸出結果:
parent event capture
child event capture
box event capture
box event bubble
child event bubble
parent event bubble
打亂事件模型綁定代碼:
box.addEventListener('click', function () {
console.log('box event bubble')
}, false)
parent.addEventListener('click', function () {
console.log('parent event capture')
}, true)
box.addEventListener('click', function () {
console.log('box event capture')
}, true)
child.addEventListener('click', function () {
console.log('child event bubble')
}, false)
parent.addEventListener('click', function () {
console.log('parent event bubble')
}, false)
child.addEventListener('click', function () {
console.log('child event capture')
}, true)
輸出結果:
parent event capture
child event capture
box event bubble
box event capture
child event bubble
parent event bubble
結論:
當多個嵌套關系的元素同時綁定了事件冒泡和事件捕獲兩種事件模型時.
除了觸發(fā)事件的那個元素(這里是最內部的藍色DIV)執(zhí)行順序和模型綁定順序一致意外.
其他外層的元素事件模型執(zhí)行順序永遠都是 事件捕獲 優(yōu)先于 事件冒泡 執(zhí)行.
所以,在某種程度上,我們可以理解為:事件捕獲 優(yōu)先于 事件冒泡 執(zhí)行.