事件委托
事件委托是指利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件,例如公司所有同事都委托前台领取快递,这样就只需要一个人收快递并负责转交给同事,而不用所有人都带公司门口去收快递。
在下面的例子中,包含了4个被单击后会执行操作的input框,按照传统做法,需要逐一添加事件处理程序
<div id="box"> <input type="button" id="add" value="添加" /> <input type="button" id="remove" value="删除" /> <input type="button" id="move" value="移动" /> <input type="button" id="select" value="选择" /> </div>
window.onload = function(){
var Add = document.getElementById("add");
var Remove = document.getElementById("remove");
var Move = document.getElementById("move");
var Select = document.getElementById("select");
Add.onclick = function(){
alert('添加');
};
Remove.onclick = function(){
alert('删除');
};
Move.onclick = function(){
alert('移动');
};
Select.onclick = function(){
alert('选择');
}
}
如果在一个复杂的程序中,对所有的单击元素都采用这种方式,那么结果就是会有数不清的代码用于添加事件处理程序,此时,我们就可以利用事件委托来解决这个问题,只需要在DOM树中尽量最高层级上添加一个事件处理程序即可。
window.onload = function(){
var oBox = document.getElementById("box");
oBox.onclick = function (ev) {
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLocaleLowerCase() == 'input'){
switch(target.id){
case 'add' :
alert('添加');
break;
case 'remove' :
alert('删除');
break;
case 'move' :
alert('移动');
break;
case 'select' :
alert('选择');
break;
}
}
}
}
性能优化
在下面有4个列表项,我们希望为这四个列表项添加鼠标移入移出事件,并通过input的点击事件添加列表项。
<input type="button" name="" id="btn" value="添加" /> <ul id="ul1"> <li>111</li> <li>222</li> <li>333</li> <li>444</li> </ul>
通常的写法是为每一个li添加移入移出事件,此时的问题是,新添加的li是没有事件的。
window.onload = function(){ var oBtn = document.getElementById("btn"); var oUl = document.getElementById("ul1"); var aLi = oUl.getElementsByTagName('li'); var num = 4; //鼠标移入变红,移出变白 for(var i=0; i<aLi.length;i++){ aLi[i].onmouseover = function(){ this.style.background = 'red'; }; aLi[i].onmouseout = function(){ this.style.background = '#fff'; } } //添加新节点 oBtn.onclick = function(){ num++; var oLi = document.createElement('li'); oLi.innerHTML = 111*num; oUl.appendChild(oLi); }; }
此时我们可以将for循环用函数包裹起来,这样就可以解决新添加节点没有绑定事件的问题了。
window.onload = function(){ var oBtn = document.getElementById("btn"); var oUl = document.getElementById("ul1"); var aLi = oUl.getElementsByTagName('li'); var num = 4; function mHover () { //鼠标移入变红,移出变白 for(var i=0; i<aLi.length;i++){ aLi[i].onmouseover = function(){ this.style.background = 'red'; }; aLi[i].onmouseout = function(){ this.style.background = '#fff'; } } } mHover (); //添加新节点 oBtn.onclick = function(){ num++; var oLi = document.createElement('li'); oLi.innerHTML = 111*num; oUl.appendChild(oLi); mHover (); }; }
现在,我们已经实现了最开始的目标了,但是,此时仅仅只是实现了功能,在性能优化上面,因为增加了DOM操作,导致浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能。
window.onload = function(){
var oBtn = document.getElementById("btn");
var oUl = document.getElementById("ul1");
var aLi = oUl.getElementsByTagName('li');
var num = 4;
//事件委托,添加的子元素也有事件
oUl.onmouseover = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == 'li'){
target.style.background = "red";
}
};
oUl.onmouseout = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == 'li'){
target.style.background = "#fff";
}
};
//添加新节点
oBtn.onclick = function(){
num++;
var oLi = document.createElement('li');
oLi.innerHTML = 111*num;
oUl.appendChild(oLi);
};
}