标签:nodename 需求 分享 evel eve 事件监听 events use 而不是
事件流
事件流描述的是从页面中接收事件的顺序。---JS高级程序设计(第3版)
DOM Level 2 Events
规定的事件流有三个阶段:①事件捕获阶段、②处于目标阶段、③事件冒泡阶段
事件委托
当需要添加的事件过多时,可以使用事件委托,而事件委托实际上利用了事件冒泡的特性。
使用事件委托还需了解事件对象(event
):在触发DOM上的某个事件时,会产生一个事件对象event
,这个对象中包含着所有与事件有关的信息。
在此仅需知道在DOM
标准中,event
拥有一个target
属性表示事件目标。
event.target
是一个触发事件的对象的引用。它与event.currentTarget
不同, 当事件处理程序在事件的冒泡或捕获阶段被调用时。(mdn)
具体Event
详情可以查看MDN:Event
如果你想要在大量子元素中单击任何一个都可以运行一段代码,您可以将事件监听器设置在其父节点上,并将事件监听器气泡的影响设置为每个子节点,而不是每个子节点单独设置事件监听器。(mdn)
以下面的html代码为例:
<ul id="list">
<li id="one">do something</li>
<li id="two">do something</li>
<li id="three">do something</li>
</ul>
当需求是单击上面每个li
标签都会执行各种操作时,使用事件委托是较好的选择。
// bad (逐个 li 添加事件)
let item1 = document.getElementById(‘one‘);
let item2 = document.getElementById(‘two‘);
let item3 = document.getElementById(‘three‘);
item1.addEventListener(‘click‘, function(){...}, false);
item1.addEventListener(‘click‘, function(){...}, false);
item1.addEventListener(‘click‘, function(){...}, false);
// event delegation (事件委托)
let list = document.getElementById(‘list‘);
list.addEventListener(‘click‘, function(e){
if (e.target && e.target.nodeName == ‘LI‘) {
switch (e.target.id) {
case ‘one‘:
do something;
break;
case ‘two‘:
do something;
break;
case ‘three‘:
do something;
break;
}
}
}, false);
注意:当li
标签被如p
、div
等撑满时,点击的target
为p
标签而不是li
标签会导致无法正确执行click
事件。
以下面的html代码为例:
<ul id="list">
<li id="one">do something</li>
<li id="two">do something</li>
<!-- 这里的 li 里面有个 p 标签 -->
<li id="three"><p>do something</p></li>
</ul>
这样的情况可以使用递归 or 循环来处理,毕竟事件委托是利用事件冒泡的特性。
//递归
let list = document.getElementById(‘list‘);
list.addEventListener(‘click‘, function(e){
eventDelegation(e.target);
}, false);
function eventDelegation(target) {
if (target && target.nodeName == ‘LI‘) {
switch (target.id) {
case ‘one‘:
do something;
return;
case ‘two‘:
do something;
return;
case ‘three‘:
do something;
return;
}
}
return eventDelegation(target.parentNode);
}
使用事件委托的优点
因为在JavaScript中,每个函数都是对象,对象越多,占用的内存也就越多,合理使用事件委托可以减少内存的占用。
注意事项
比较适合使用事件委托的事件:click
、mousedown
、mouseup
等,而如mouseout
、mouseover
等则不太适合使用事件委托(虽然mouseout
这些事件也冒泡,但通常需要确定元素的位置,所以不太推荐使用事件委托)。
另外不会冒泡的事件是不适合使用事件委托的。
标签:nodename 需求 分享 evel eve 事件监听 events use 而不是
原文地址:https://www.cnblogs.com/guolao/p/10088087.html