利用冒泡的原理,把事件加到父元素或祖先元素上,触发执行效果。
在Js中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器的重绘与重排的次数就越多,就会延长整个页面的交互就绪时间。这就是为什么性能优化的主要思想之一就是减少DOM操作的原因。
比如我们有100个li,每个li都有相同的click点击事件。如果用for循环的方法来遍历所有的li并添加事件,会不断的进行DOM操作。如果用事件委托,就会将所有的操作放到js程序里面,与DOM的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能。
并且每一个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率越大,性能就越差。如果用事件委托,就可以只对它的父级这一个对象进行操作,这样就需要一个内存空间就够了。
事件委托是利用事件的冒泡原理实现的。给最外面的元素添加点击事件,里面的子元素做点击事件时,都会冒泡到最外层的元素上,所以都会触发,这就是事件委托,委托它们父级代为执行事件。
优点1:提高事件的处理速度,减少内存的占用
实现功能,点击不同的li,弹出不同的内容
一般方法:
1 <ul id="list"> 2 <li id="item1">111</li> 3 <li id="item2">222</li> 4 <li id="item3">333</li> 5 </ul> 6 <script> 7 var item1 = document.getElementById('item1'); 8 var item2 = document.getElementById('item2'); 9 var item3 = document.getElementById('item3') 10 item1.onclick = function () { 11 alert('hello item1'); 12 } 13 item2.onclick = function () { 14 alert('hello item2'); 15 } 16 item3.onclick = function () { 17 alert('hello item3'); 18 } 19 </script>
事件委托:
1 <ul id="list"> 2 <li id="item1">111</li> 3 <li id="item2">222</li> 4 <li id="item3">333</li> 5 </ul> 6 <script> 7 var item1 = document.getElementById('item1'); 8 var item2 = document.getElementById('item2'); 9 var item3 = document.getElementById('item3') 10 11 var list = document.getElementById('list'); 12 13 list.onclick = function (event) { 14 var event = event || window.event; 15 var target = event.target || event.srcElement; 16 if (target == item1) { 17 alert('hello item1'); 18 } else if (target == item2) { 19 alert('hello item2'); 20 } else if (target == item3) { 21 alert('hello item3'); 22 } 23 } 24 </script>
优点2:可以为动态添加的元素动态地添加事件
动态添加DOM元素,传统方式不能为动态添加的元素动态地添加事件。事件委托可以。
1 <ul id="list"> 2 <li id="item1">item1</li> 3 <li id="item2">item2</li> 4 <li id="item3">item3</li> 5 </ul> 6 <script> 7 var list = document.getElementById('list'); 8 var items = list.getElementsByTagName('li'); 9 10 for (var i = 0; i < items.length; i++) { 11 (function (i) { 12 items[i].onclick = function () { 13 alert(items[i].innerHTML); 14 } 15 })(i) 16 } 17 18 var node = document.createElement('li'); 19 var textnode = document.createTextNode('item4'); 20 node.appendChild(textnode); 21 list.appendChild(node); 22 </script>
上述代码执行后,点击item1,item2,item3都会弹出内容,点击item4没有反应。
1 <ul id="list"> 2 <li id="item1">item1</li> 3 <li id="item2">item2</li> 4 <li id="item3">item3</li> 5 </ul> 6 <script> 7 var list = document.getElementById('list'); 8 9 list.onclick = function (e) { 10 var e = e || window.event; 11 var target = event.target || event.srcElement; 12 if (target.nodeName == 'LI') { 13 alert(target.innerHTML); 14 } 15 } 16 var node = document.createElement('li'); 17 var textnode = document.createTextNode('item4'); 18 node.appendChild(textnode); 19 list.appendChild(node); 20 </script>
当点击item4时,item4有事件响应。事件委托可以为动态添加的DOM元素动态的添加事件。
1 <ul id="list"> 2 <li id="item1"><p>item1</p></li> 3 <li id="item2"><div>item2</div></li> 4 <li id="item3"><span>item3</span></li> 5 </ul>
当每一个li里面还有子元素,并且子元素互不相同时,e.target就可能是p或者div或者span,这时的事件代理可以如下
1 var list = document.getElementById('list'); 2 list.onclick = function (e) { 3 var e = e || window.event; 4 var target = e.target || e.srcElement; 5 while (target !== list) { 6 if (target.tagName.toLowerCase() == 'li') { 7 alert('li click'); 8 break; 9 } else { 10 target = target.parentNode; 11 } 12 } 13 }
适合用事件委托的事件有:click,mousedown,mouseup,keydown,keyup,keypress
不适合的有:mouseover,mouseout,mousemove(这些事件每次都要计算位置,不好把控,处理起来不太容易)
focus,blur(本身没有用冒泡的特性,不能用事件委托)