概念
事件委托是依靠事件冒泡, 只需要指定一个事件处理程序, 绑定一次就可以处理一类的事件. 举个例子: 假如有一个旅游团, 其组成有旅游团公司 导游 旅行者. 旅游团公司想征求下旅行者是否愿意更改路线, 这里就有两种方式了. 第一种: 旅游团公司直接和每个旅行者建立联系, 询问是否愿意更改路线. 第二种: 旅游团公司直接和导游取得联系, 又导游来反馈给旅游团公司. 其实第一种就是和每一个节点建立联系, 最直接, 但是也是比较耗费资源的, 第二种就是事件委托机制了, 把联系委托给导游, 最终旅游者的意见会反馈到导游那里, 然后旅游团公司再在导游那里做出反应.
优点
减少资源消耗. 因为每次绑定一个事件是需要消耗系统资源的, 内存啊之类的.
减少 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])
- }
- }
- })
来源: http://www.jianshu.com/p/fa48628f4fb3