说到事件代理,首先得知道js的事件冒泡机制。
事件冒泡是指在一个dom节点触发一个事件比如onclick事件以后,这个事件会继续往节点的父节点传递,若父节点也绑定了onclick事件,则同样会触发父节点的onclick事件,然后继续往父节点的父节点传递....由内层往外层传递。
事件代理就是利用了事件冒泡机制,将一个节点的事件处理,交给它的父级去处理。举个栗子:若为多个li标签绑定事件。
1.一般的事件绑定方法:
1 <ul id="list"> 2 <li>1</li> 3 <li>2</li> 4 <li>3</li> 5 <li>4</li> 6 <li>5</li> 7 </ul>
1 <script> 2 var list=document.getElementById(‘list‘); 3 var lis=list.getElementsByTagName(‘li‘); 4 for(var i=0;i<5;i++){ 5 lis[i].addEventListener(‘click‘,function(){ 6 alert(‘li click‘); 7 }) 8 } 9 </script>
2.使用事件代理
1 <script> 2 var list=document.getElementById(‘list‘); 3 // 让li的父节点绑定click事件,然后在内部判断事件触发的目标是否是li标签,如果是的话,执行相应操作,这样能达到直接绑定li标签同样的效果,且只用绑定一次 4 list.addEventListener(‘click‘,function(e){ // 5 if(e.target.nodeName===‘LI‘){ 6 alert(‘li click‘); 7 } 8 }) 9 </script>
从以上可以看出在使用事件代理可以减少dom操作,优化性能。使用代理还有一个好处就是:
例如在给动态加载的img图片绑定事件时,使用代理就不用每次给新增的标签绑定事件。例如:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>事件代理</title> 6 </head> 7 <body> 8 <div id="box"> 9 <img src="" alt="1"> 10 <img src="" alt="2"> 11 <img src="" alt="3"> 12 <img src="" alt="4"> 13 <img src="" alt="5"> 14 <!-- 下面还有很多需要动态加载的图片 --> 15 </div> 16 <button id="addImg">添加图片</button> 17 <script> 18 var box=document.getElementById(‘box‘); 19 var i=5; 20 var btn=document.getElementById(‘addImg‘); 21 btn.addEventListener(‘click‘,function(){ 22 var img=document.createElement(‘img‘); 23 i++; 24 img.alt=i; 25 box.appendChild(img); 26 }) 27 // 使用事件代理 28 box.addEventListener(‘click‘,function(e){ 29 if(e.target.nodeName===‘IMG‘){ 30 alert(‘img click‘); 31 } 32 }); 33 //不使用事件代理时,新增的图片没有事件绑定,需要重新绑定才行 34 /*var imgs=box.getElementsByTagName(‘img‘); 35 for(var j=0;j<i;j++){ 36 imgs[j].addEventListener(‘click‘,function(){ 37 alert(‘img click‘); 38 }) 39 }*/ 40 </script> 41 </body> 42 </html>
3.写一个通用的事件绑定函数,既可以使用代理,也可以不使用代理
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件</title> </head> <body> <div id="div1"> <a href="http://imooc.com" id="link1">imooc.com</a> <a href="http://imooc.com" id="link2">imooc.com</a> <a href="http://imooc.com" id="link3">imooc.com</a> <a href="http://imooc.com" id="link4">imooc.com</a> <a href="http://imooc.com" id="link5">imooc.com</a> <a href="http://imooc.com" id="link6">imooc.com</a> <p id="p1">this is p1</p> <p id="p2">this is p2</p> </div> <hr> <div id="div2"> <p id="p3">this is p3</p> <p id="p4">this is p4</p> </div> <script> //简单的事件绑定函数 var link1=document.getElementById(‘link1‘); // function on(ele,type,fn){ // ele.addEventListener(type,fn); // } // on(link1,‘click‘,function(e){ // e.preventDefault(); // alert(‘clicked‘); // }) //事件代理 var div1=document.getElementById(‘div1‘); // div1.addEventListener(‘click‘,function(e){ // e.preventDefault(); // if(e.target.nodeName===‘A‘){ // alert(‘clicked‘); // } // }) //完整的绑定事件函数 function bindEvent(ele,type,selector,fn){ if(fn==null){ fn=selector; selector=null; } var target; ele.addEventListener(type,function(e){ if(selector){ //事件代理 target=e.target; //element.matches(selector),返回true或false if(target.matches(selector)){ fn.call(target,e); } }else{ //非事件代理 fn(e); } }); } bindEvent(div1,‘click‘,‘a‘,function(e){ e.preventDefault(); alert(this.innerHTML); }); var p1=document.getElementById(‘p1‘); bindEvent(p1,‘click‘,function(e){ alert(p1.innerHTML); }); </script> </body> </html>