[HTML] target phase事件顺序
我们知道addEventListener
的第三个参数,
useCapture
用来标识该事件监听函数用于处理什么阶段的事件。
不写useCapture
,或者useCapture=false
,表示用于处理冒泡阶段的事件,
useCapture=true
,表示用于处理捕获阶段的事件。
可是,关于事件与事件监听函数和目标阶段的事件顺序,还有值得注意的地方,
<div id="div1">
<input id="button1" type="button" value="test">
</div>
<script>
var btn=document.querySelector('#button1');
var div=document.querySelector('#div1');
div.addEventListener('click',function(e){
console.log(1,e.target,e.currentTarget);
},false);
btn.addEventListener('click',function(e){
console.log(2,e.target,e.currentTarget);
},false);
btn.addEventListener('click',function(e){
console.log(3,e.target,e.currentTarget);
},true);
btn.addEventListener('click',function(e){
console.log(4,e.target,e.currentTarget);
},false);
div.addEventListener('click',function(e){
console.log(5,e.target,e.currentTarget);
},true);
</script>
运行结果如下:
5 <input id="button1" type="button" value="test"> <div id="div1">…</div>
2 <input id="button1" type="button" value="test"> <input id="button1" type="button" value="test">
3 <input id="button1" type="button" value="test"> <input id="button1" type="button" value="test">
4 <input id="button1" type="button" value="test"> <input id="button1" type="button" value="test">
1 <input id="button1" type="button" value="test"> <div id="div1">…</div>
我们看到,
div
上在捕获阶段的事件监听函数是最先被调用的(5号),
随后按注册顺序调用了btn
上目标阶段的事件监听函数(2,3,4号),
最后调用了div
上冒泡阶段的事件监听函数(1号)。
(1)关于事件和事件监听函数是其中一个容易引起混淆的点,
当我们点击btn
,准备触发btn
上名为click
的事件时,
无论btn
的祖先和btn
上是否注册了事件监听函数,click
事件都会在它们上面触发的,
只不过如果没有注册事件监听函数,就忽略处理click事件罢了。
因此,body
上的,html
上的click
事件(包括冒泡和捕获)实际上也是触发了的。
(2)另外一个点是,事件发生实际上包含了3个阶段,捕获阶段(capture phase),目标阶段(target phase)和冒泡阶段(bubble phase)。
人们提及捕获阶段和冒泡阶段较多,容易忽略目标阶段。
事实上,目标阶段事件监听函数的调用顺序与注册顺序有关。
Next, the implementation must determine the current target's candidate event listeners. This must be the list of all event listeners that have been registered on the current target in their order of registration.
因此,目标阶段的2,3,4号事件监听函数会按注册顺序调用,
而不是先调用useCapture=true
的事件监听函数,再调用useCapture=false
事件监听函数。
useCapture
只对捕获和冒泡阶段有用,对目标阶段无效。