详解js的事件代理(委托)
JavaScript事件代理(委托)一般用于以下情况:
1.事件注册在祖先级元素上,代理其子级元素。可以减少事件注册数量,节约内存开销,提高性能。
2.对js动态添加的子元素可自动绑定事件。
之前一直用各种js库的事件代理,如jQuery,非常方便实用。今天尝试用原生js实现该功能。
varaddEvent=(function(){ if(document.addEventListener){ returnfunction(element,type,handler){ element.addEventListener(type,handler,false); }; }elseif(document.attachEvent){ returnfunction(element,type,handler){ element.attachEvent('on'+type,function(){ handler.apply(element,arguments); }); }; }else{ returnfunction(element,type,handler){ element['on'+type]=function(){ returnhandler.apply(element,arguments); }; }; } })(), getClassElements=function(parentElement,classname){ varall,element,classArr=[],classElements=[]; if(parentElement.getElementsByClassName){ returnparentElement.getElementsByClassName(classname); }else{ all=parentElement.getElementsByTagName('*'); for(vari=0,len=all.length;i<len;i++){ element=all[i]; classArr=element&&element.className&&element.className.split(''); if(classArr){ for(varj=0;j<classArr.length;j++){ if(classArr[j]===classname){ classElements.push(element); } } } } returnclassElements; } }, delegate=function(){//参数:element,type,[selector,]handler varargs=arguments, element=args[0], type=args[1], handler; if(args.length===3){ handler=args[2]; returnaddEvent(element,type,handler); } if(args.length===4){ selector=args[2]; handler=args[3]; returnaddEvent(element,type,function(event){ varevent=event||window.event, target=event.target||event.srcElement, quickExpr=/^(?:[a-zA-Z]*#([\w-]+)|(\w+)|[a-zA-Z]*\.([\w-]+))$/, match, idElement, elements, tagName, count=0, len; if(typeofselector==='string'){ match=quickExpr.exec(selector); if(match){ //#IDselector if(match[1]){ idElement=document.getElementById(match[1]); tagName=match[0].slice(0,match[0].indexOf('#')); //tagselector }elseif(match[2]){ elements=element.getElementsByTagName(selector); //.classselector }elseif(match[3]){ elements=getClassElements(element,match[3]); tagName=match[0].slice(0,match[0].indexOf('.')); } } if(idElement){ if(tagName?tagName===idElement.nodeName.toLowerCase()&&target===idElement:target===idElement){ returnhandler.apply(idElement,arguments); } }elseif(elements){ for(len=elements.length;count<len;count++){ if(tagName?tagName===elements[count].nodeName.toLowerCase()&&target===elements[count]:target===elements[count]){ returnhandler.apply(elements[count],arguments); } } } } }); } };
主要是用apply改变this的指向
handler.apply(idElement,arguments); handler.apply(elements[count],arguments);
测试一下:
<style> #outer{padding:50px;background-color:lightpink;} #inner{padding:30px;background-color:aliceblue;} #paragraph1,#paragraph3{background-color:cadetblue} </style>
<divid="outer">outer <divid="inner">inner <pid="paragraph1"class="parag1">paragraph1</p> <pid="paragraph2"class="parag">paragraph2</p> <span>span</span> <pid="paragraph3"class="parag">paragraph3</p> </div> </div>
varouter=document.getElementById('outer'); delegate(outer,'click',function(){ console.log(this.id);//outer });
delegate(outer,'click','p',function(){ console.log(this.id);//点击paragraph1元素,输出其id为"paragraph1" });
模仿jQuery的风格,优化代码:
(function(){ var$=function(element){ returnnew_$(element); }; var_$=function(element){ this.element=element&&element.nodeType===1?element:document; }; _$.prototype={ constructor:_$, addEvent:function(type,handler,useCapture){ varelement=this.element; if(document.addEventListener){ element.addEventListener(type,handler,(useCapture?useCapture:false)); }elseif(document.attachEvent){ element.attachEvent('on'+type,function(){ handler.apply(element,arguments); }); }else{ element['on'+type]=function(){ returnhandler.apply(element,arguments); }; } returnthis; }, getClassElements:function(classname){ varelement=this.element,all,ele,classArr=[],classElements=[]; if(element.getElementsByClassName){ returnelement.getElementsByClassName(classname); }else{ all=element.getElementsByTagName('*'); for(vari=0,len=all.length;i<len;i++){ ele=all[i]; classArr=ele&&ele.className&&ele.className.split(''); if(classArr){ for(varj=0;j<classArr.length;j++){ if(classArr[j]===classname){ classElements.push(ele); } } } } returnclassElements; } }, delegate:function(){//参数:type,[selector,]handler varself=this, element=this.element, type=arguments[0], handler; if(arguments.length===2){ handler=arguments[1]; returnself.addEvent(type,handler); }elseif(arguments.length===3){ selector=arguments[1]; handler=arguments[2]; returnself.addEvent(type,function(event){ varevent=event||window.event, target=event.target||event.srcElement, quickExpr=/^(?:[a-zA-Z]*#([\w-]+)|(\w+)|[a-zA-Z]*\.([\w-]+))$/, match, idElement, elements, tagName, count=0, len; if(typeofselector==='string'){ match=quickExpr.exec(selector); if(match){ //#IDselector if(match[1]){ idElement=document.getElementById(match[1]); tagName=match[0].slice(0,match[0].indexOf('#')); //tagselector }elseif(match[2]){ elements=element.getElementsByTagName(selector); //.classselector }elseif(match[3]){ elements=self.getClassElements(match[3]); tagName=match[0].slice(0,match[0].indexOf('.')); } } if(idElement){ if(tagName?tagName===idElement.nodeName.toLowerCase()&&target===idElement?target===idElement){ returnhandler.apply(idElement,arguments); } }elseif(elements){ for(len=elements.length;count<len;count++){ if(tagName?tagName===elements[count].nodeName.toLowerCase()&&target===elements[count]:target===elements[count]){ returnhandler.apply(elements[count],arguments); } } } } }); } } }; window.$=$; return$; }());
使用如下:
varouter=document.getElementById('outer'); $(outer).delegate('click','.parag',function(event){ console.log(this.id); });
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持毛票票!