• js的事件委托


    什么是事件委托呢?

    首先,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件。举个例子,比如说送快递,如果一个快递员送一个公司的快递,他可以选择在公司联系每个人来取这个快递,当然另一种方法就是把快递让前台的MM代收,然后公司的人只要自己来前台取就ok了,虽然结果是一样的,但是效率却变快了许多。这里面可以把员工来取快递的行为看作是事件冒泡(什么是事件冒泡上篇文章有提)。

    特别注意:

    事件委托是通过事件冒泡实现的,所以如果子级的元素阻止了事件冒泡,那么事件委托也将失效!

    举个简单的事件委托例子:

    下面代码是一个普通的事件绑定

    <ul id="ul">
      <li>aaaaaaaa</li>
      <li>bbbbbbbb</li>
      <li>cccccccc</li>
    </ul>
    window.onload = function(){
      var oUl = document.getElementById("ul");
      var aLi = oUl.getElementsByTagName("li");
    
      for(var i=0; i<aLi.length; i++){
        aLi[i].onmouseover = function(){
          this.style.background = "red";
        }
        aLi[i].onmouseout = function(){
          this.style.background = "";
        }
      }
    }

    这样子我们可以通过for循环来遍历每一个li节点从而实现事件的绑定。但是有一个问题,上面代码只有三个dom界面,如果有需求需要的dom节点特别多,那么这就存在了性能的问题了。

    下面我们可以用事件委托的方式来实现这样的效果:

    oUl.onmouseover = function(e){
        var e = e || window.event;
        var target = e.target || e.srcElement;
        //alert(target.innerHTML);
        if(target.nodeName.toLowerCase() == "li"){
        target.style.background = "red";
        }
      }
      oUl.onmouseout = function(e){
        var e = e || window.event;
        var target = e.target || e.srcElement;
        //alert(target.innerHTML);
        if(target.nodeName.toLowerCase() == "li"){
        target.style.background = "";
        }
      }
    }

    我们通过event.target来实现事件委托,这里用到了事件源:event。什么是事件源呢?记住不管在那个事件中,只要你操作的那个元素就是事件源。

    显而易见,这种方法就避免了for循环,从而提高了代码的性能,这也是事件委托的第一个好处:提高性能!

    让我们再看一段代码:

    下面的代码是如何操作后添加的dom元素

    window.onload = function(){
      var oUl = document.getElementById("ul");
      var aLi = oUl.getElementsByTagName("li");
      var oBtn = document.getElementById("btn");
      var iNow = 4;
      for(var i=0; i<aLi.length; i++){
        aLi[i].onmouseover = function(){
          this.style.background = "red";
        }
        aLi[i].onmouseout = function(){
          this.style.background = "";
        }
      }
      oBtn.onclick = function(){
        iNow ++;
        var oLi = document.createElement("li");
        oLi.innerHTML = 1111 *iNow;
        oUl.appendChild(oLi);
      }
    }

    这段代码用到了window.onload来实现事件的绑定,不过不用这个方法,那么事件肯定是失效。因为你绑定事件时根本就不存在这个dom元素,那么事件必然事件。

    而事件委托就不会有这种问题。

    window.onload = function(){
      var oUl = document.getElementById("ul");
      var aLi = oUl.getElementsByTagName("li");
      var oBtn = document.getElementById("btn");
      var iNow = 4;
      oUl.onmouseover = function(e){
        var e = e || window.event;
        var target = e.target || e.srcElement;
        //alert(target.innerHTML);
        if(target.nodeName.toLowerCase() == "li"){
        target.style.background = "red";
        }
      }
      oUl.onmouseout = function(e){
        var e = e || window.event;
        var target = e.target || e.srcElement;
        //alert(target.innerHTML);
        if(target.nodeName.toLowerCase() == "li"){
        target.style.background = "";
        }
      }
      oBtn.onclick = function(){
        iNow ++;
        var oLi = document.createElement("li");
        oLi.innerHTML = 1111 *iNow;
        oUl.appendChild(oLi);
      }
    }
    IE:window.event.srcElement
    标准下:event.target
    nodeName:找到元素的标签名

    其实事件委托的核心不过是通过event.target(当前事件元素).nodeName(dom元素的标签名)取到标签,然后用event.target.style.xxx(例子中给的是background)来操作dom
    window.event.srcElement是为了兼容ie
    下面是兼容浏览器写出的一个target事件
        var e = e || window.event;
        var target = e.target || e.srcElement;

    这个如实事件委托的最核心,最有用的地方(个人认为),就是能够给后插入的dom节点绑定事件。一般我们用ajax调用接口返回的是一个大的json串,然后通过这个返回json动态插入数据(dom),这时候我们使用事件委托就不会出来事件绑定失效了。

    jquery下的事件委托:

    $(document).on('click','li',function(){
        alert('这是一个li!!!');
    });

    这就是一个事件委托。其实最开始的事件委托是封装的bind(),live()和delegate(),

    首先我们先说bind()

    $("ul li").bind("click", function(){
      alert('这是一个li!!!');
    });

    问题是,如果ul中要绑定1000个里,那么查找遍历1000个li会导致脚本运行速度很慢,而保存1000个li元素和事件处理程序也会占用大量的内存,所以这种方式我们不推荐。

    下面我们来说第二种live()

    $("ul li").live("click", function(){
      alert('这是一个li!!!');
    });
    live()事件委托可以解决上述两个问题。具体到代码上,只要用jQuery 1.3新增的.live()方法代替.bind()方法即可。
    但是live也是有问题的。
    1.$()函数会找到当前页面中的所有li元素并创建jQuery对象,但在确认事件目标时却不用这个li元素集合,而是使用选择符表达式与event.target或其祖先元素进行比较,因而生成这个jQuery对象会造成不必要的开销。

    2.默认把事件绑定到$(document)元素,如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致性能损失。
    这些问题也是.live()方法饱受诟病的一个重要原因。
    为了解决上面两个方法带来的问题,jquery在1.4.2版本引入了一个新的delegate(),代码如下:
    
    
    $("ul li").delegate("click", function(){
      alert('这是一个li!!!');
    });
    
    
    jquery 1.7为了解决.bind()、.live()和.delegate()并存造成的不一致性问题,将会增加一对新的事件方法:.on()
    所以现在我们用jquery都是用on绑定事件(也是我最开始写的事件委托的方式)。jquery规定on()中的第二个参数如果是dom元素,则为事件委托,否则为正常的事件绑定。
    最后:希望本文所述对大家的事件委托理解有所帮助!!!
     
     
  • 相关阅读:
    中医手诊原理
    半月痕
    0020 教您新手修车的五种实用技巧
    下面说说我开车12年来的一些心得
    创建电子邮件信纸
    交通事故责任划分2011版(图解)
    育儿语录
    汽车中控台那些按钮是什么用的?
    我的书中的部分函数
    纠结的书名
  • 原文地址:https://www.cnblogs.com/jcscript/p/5634439.html
Copyright © 2020-2023  润新知