事件委托:将原本应该绑定在元素本身的事件绑定在他的父元素或者是祖先元素中,利用事件冒泡的原理。
例如1:在ul标签下有1000个li,如果我们要为所有的li添加鼠标 “移进移出”事件,一般我们会想到直接循环在li元素的本身添加事件,但是这样会严重的影响页面的显示性能,在这个时候我们就可以用到js的事件委托,将事件委托在他们的父元素上:
一般解法:
<!DOCTYPE html> <html> <span style="white-space:pre"> </span><head> <meta charset="UTF-8"> <title>事件委托</title> <style type="text/css"> ul { padding: 0; margin: 0; } #num li { list-style-type: none; font-size: 16px; background-color: #ccc; text-align: center; margin: 10px 0; width: 200px; } #name { width: 150px; } </style> <script type="text/javascript"> window.onload = function() { var oUl = document.getElementById("num"); var oLi = document.getElementsByTagName("li"); var len = oLi.length; for(var i=0; i<len; i++){ oLi[i].onmouseover = function(){ this.style.background = "red"; } oLi[i].onmouseout = function(){ this.style.background = ""; } } /*添加新节点*/ var osub = document.getElementById("sub"); //提交 var oname = document.getElementById("name"); //节点信息 osub.onclick = function() { var nli = document.createElement("li"); /*判断节点是否有内容,如果有的话就添加在ul的子元素后面*/ if (oname.value != "") { nli.innerHTML = oname.value; oUl.appendChild(nli); } } } </script> </head> <body> <ul id="num"> <li>1</li> <li>2</li> <li>3</li> </ul> <input type="text" id="name" placeholder="请输入节点内容" /> <input type="submit" id="sub" /> </body> </html>
你会发现当我们将鼠标移入移出最新添加的li元素的时候,并没有触发onmouseout() 和 onmouseover()函数,这是因为在我们执行新添加元素的时候,for循环已经结束了,所以就未绑定相对应的事件。
事件委托解法:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>事件委托</title> <style type="text/css"> ul { padding: 0; margin: 0; } #num li { list-style-type: none; font-size: 16px; background-color: #ccc; text-align: center; margin: 10px 0; width: 200px; } #name { width: 150px; } </style> <script type="text/javascript"> window.onload = function() { var oUl = document.getElementById("num"); var oLi = document.getElementsByTagName("li"); /* 这里要用到事件源:event 对象事件源,不管在哪个事件中,只要你操作的那个元素就是事件源。 IE:window.event.srcElement 标准下:event.target nodeName:找到元素的标签名 */ oUl.onmouseover = function(e) { /*获取事件源*/ var e = e || window.event; var target = e.target || e.srcElement; /*获取事件源的元素名称*/ if (target.nodeName.toLowerCase() == "li") { target.style.background = "red"; }; }; oUl.onmouseout = function(e) { /*获取事件源*/ var e = e || window.event; var target = e.target || e.srcElement; /*获取事件源的元素名称*/ if (target.nodeName.toLowerCase() == "li") { target.style.background = ""; } } /*添加节点*/ var osub = document.getElementById("sub"); //提交 var oname = document.getElementById("name"); //节点信息 osub.onclick = function() { var nli = document.createElement("li"); /*判断节点是否有内容,如果有的话就添加在ul的子元素后面*/ if (oname.value != "") { nli.innerHTML = oname.value; oUl.appendChild(nli); } } } </script> </head> <body> <ul id="num"> <li>1</li> <li>2</li> <li>3</li> </ul> <input type="text" id="name" placeholder="请输入节点内容" /> <input type="submit" id="sub" /> </body> </html>
但是在原来的html未改变的情况下,如果我们使用事件委托的方式来触发事件的话,可以发现最新添加的li元素可以触发onmouseout() 和 onmouseover()函数的事件。
顺道推荐一篇Jquery的事件委托文章点击打开链接
事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。
事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。
事件起泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)来组织事件的冒泡传播。