概念
事件委托是依靠事件冒泡,只需要指定一个事件处理程序,绑定一次就可以处理一类的事件。举个例子:假如有一个旅游团,其组成有旅游团公司
导游
旅行者
。旅游团公司想征求下旅行者是否愿意更改路线,这里就有两种方式了。第一种:旅游团公司直接和每个旅行者建立联系,询问是否愿意更改路线。第二种:旅游团公司直接和导游取得联系,又导游来反馈给旅游团公司。其实第一种就是和每一个节点建立联系,最直接,但是也是比较耗费资源的,第二种就是事件委托机制了,把联系委托给导游,最终旅游者的意见会反馈到导游那里,然后旅游团公司再在导游那里做出反应。
优点
减少资源消耗。因为每次绑定一个事件是需要消耗系统资源的,内存啊之类的。
减少dom操作,就可以减少页面的重绘和结构重排,提升流畅性。
实例
<!-- 第一种比较简单的 -->
<div id="公司">
<ul id="导游">
<li>123</li>
<li>345</li>
<li>567</li>
</ul>
</div>
var ul = document.getElementById("导游");
ul.addEventListener("click", function (event) {
event.target.style.color = "red";
console.log(event.target);
})
//<li>345</li> 等
<!-- 第二种,假如以下这种结构,我还是想将li的事件委托给ul来处理,怎么办? -->
<div id="公司">
<ul id="导游">
<li>123</li>
<li>345</li>
<li><span>xx</span></li>
<li><span>xx <i>yy</i></span></li>
</ul>
</div>
//如果还是用之前的方法
var ul = document.getElementById("导游");
ul.addEventListener("click", function (event) {
event.target.style.color = "red";
console.log(event.target);
})
//则必然会出现
//<span>xx <i>yy</i></span> 这里触发就没有在li上了
//这里我的解决方案就是使用event下的另外一个属性,path,这个属性记录了从根元素到event.target目标元素的触发过程堆栈。
var ul2 = document.getElementById("导游");
ul2.addEventListener("click", function (event) {
var max = event.path.indexOf(event.currentTarget);
for (var i = max; i >= 0; i--) { //这里就在寻找 委托目标 和 实际触发的目标之间 是否存在 li 元素,找到就表示存在,就执行相应的动作即可
if (event.path[i].nodeName.toLowerCase() === 'li') {
event.path[i].style.color = "red";
console.log(event.path[i])
}
}
})
网友评论