一般情况下我们对一个DOM元素绑定事件时有三种方式
//省略之前代码 <div onclick="eventFn()"></div> aDiv=onclick=function(){ //... } aDiv.addEventListener('click',function(){ //... },false)
这样写是没有任何问题的(当然方法1并不可取)
但是在实际开发中我们会碰到诸如十几二十个li元素绑定事件的情况,甚至更多的元素,那么事件绑定这种给每一个元素都循环绑定的方式就会影响性能
所以我们可以利用事件冒泡的机制,使用事件委托的方法避免过多的性能损耗
简单来说就是将事件绑定到尽可能层级较高的父元素上,而元素触发事件后会逐级向上冒泡,利用事件对象event来判断事件冒泡是否传播到我们需要绑定事件的元素上
举个栗子
//有这样一个html结构 <ul id="ul"> <li>aaaaaaaa</li> <li>bbbbbbbb</li> <li>cccccccc</li> </ul>
我们需要鼠标每次移入移出li元素改变li的背景颜色
首先我们利用传统的事件绑定来做,代码如下
var oUl = document.getElementById("ul"); var aLi = oUl.getElementsByTagName("li"); for(var i=0; i<aLi.length; i++){ aLi[i].onmouseover = function(){ this.style.background = "red"; } aLi[i].onmouseout = function(){ this.style.background = ""; } }
而使用事件委托实现是这样的
var oUl = document.getElementById("ul"); var aLi = oUl.getElementsByTagName("li"); //这里先把事件添加到ul上 oUl.onmouseover=function(e){ //这里需要用到事件对象来判断触发的元素 var ev=e||window.event; var target = ev.target || ev.srcElement; //兼容各大浏览器 if(target.nodeName.toLowerCase() == "li"){ //判断事件冒泡是否传播到li元素 target.style.background = "red"; } oUl.onmouseout = function(ev){ var ev = ev || window.event; var target = ev.target || ev.srcElement; //alert(target.innerHTML); if(target.nodeName.toLowerCase() == "li"){ target.style.background = ""; } } }
这样写看起来麻烦了不少,实际上能为我们节省很大一部分的性能损耗
事件委托还有另外一个好处
在传统的事件绑定中,假如上面的ul中的li元素数量是不固定的,也就是说有可能在实际运行中会产生动态添加的li元素
那么这个时候事件绑定是无法给动态生成的li元素绑定事件的,所以就必须用事件委托来给新生成的元素添加事件