事件委托

事件委托是指利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件,例如公司所有同事都委托前台领取快递,这样就只需要一个人收快递并负责转交给同事,而不用所有人都带公司门口去收快递。

在下面的例子中,包含了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);
     };
}
posted on 2018-07-03 20:31  紅葉  阅读(202)  评论(0编辑  收藏  举报