JavaScript事件的委派与事件的绑定

事件的委派

在很多需求中,通常元素是动态创建添加到一个父元素中的,这时候我们点击新增的元素是没有反应的

<script type="text/javascript">
    window.onload = function(){
        var u1 = document.getElementById("u1");
        var btn01 = document.getElementById("btn01");
        btn01.onclick = function(){
            var li = document.createElement("li"); //创建一个li
            li.innerHTML = "<a href='javascript:;' class='link'>新建的超链接</a>";
            u1.appendChild(li);  //点击按钮以后添加超链接,将li添加到ul中
        };
        
        /*
         * 为每一个超链接都绑定一个单击响应函数
         * 这里我们为每一个超链接都绑定了一个单击响应函数,这种操作比较麻烦,
         *     而且这些操作只能为已有的超链接设置事件,而新添加的超链接必须重新绑定
         */
        //获取所有的a,这样其实后面新增的li点击没效果
        var allA = document.getElementsByTagName("a");
        //遍历
        for(var i=0 ; i<allA.length ; i++){
            allA[i].onclick = function(){
                alert("我是a的单击响应函数!!!");
            };
        }
    };
</script>
</head>
<body>
    <button id="btn01">添加超链接</button>
    <ul id="u1" style="background-color: #bfa;">
        <li>
            <p>我是p元素</p>
        </li>
        <li><a href="javascript:;" class="link">超链接一</a></li>
        <li><a href="javascript:;" class="link">超链接二</a></li>
        <li><a href="javascript:;" class="link">超链接三</a></li>
    </ul>
</body>

点击新建的超链接,不会有任何反应,没有触发到点击事件。这时候我们希望,只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的

可以尝试将其绑定给元素的共同的祖先元素

指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素(这个就是冒泡的好处),从而通过祖先元素的响应函数来处理事件

事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能

<script type="text/javascript">
    window.onload = function(){
        var u1 = document.getElementById("u1");
        var btn01 = document.getElementById("btn01");
        btn01.onclick = function(){
            var li = document.createElement("li"); //创建一个li
            li.innerHTML = "<a href='javascript:;' class='link'>新建的超链接</a>";
            u1.appendChild(li);  //点击按钮以后添加超链接,将li添加到ul中
        };
        // 为ul绑定一个单击响应函数
        u1.onclick = function(event){
            event = event || window.event;
            //如果触发事件的对象是我们期望的元素,则执行否则不执行
            if(event.target.className == "link"){
                console.log(this) // this是ul这个元素
                console.log(event.target) // event中的target表示的触发事件的对象
                alert("我是ul的单击响应函数");
            }
        };
    };
</script>
</head>
<body>
    <button id="btn01">添加超链接</button>
    <ul id="u1" style="background-color: #bfa;">
        <li>
            <p>我是p元素</p>
        </li>
        <li><a href="javascript:;" class="link">超链接一</a></li>
        <li><a href="javascript:;" class="link">超链接二</a></li>
        <li><a href="javascript:;" class="link">超链接三</a></li>
    </ul>
</body>

这时候点击新建的超链接就有效果了

事件的绑定

使用 对象.事件 = 函数 的形式绑定响应函数,它只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定了多个,则后边会覆盖掉前边的

<body>
  <button id="btn01">点我一下</button>
</body>
</html>
<script type="text/javascript">
  window.onload = function(){
    var btn01 = document.getElementById("btn01");
    //为btn01绑定一个单击响应函数
    btn01.onclick = function(){
      alert(1);
    };

    //为btn01绑定第二个响应函数
    btn01.onclick = function(){
      alert(2);
    };
  };
</script>

执行结果第二个绑定的响应函数覆盖了第一个绑定的函数,使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数

这样当事件被触发时,响应函数将会按照函数的绑定顺序执行,addEventListener(),通过这个方法也可以为元素绑定响应函数

参数:第一个参数:事件的字符串,不要on。第二个参数:回调函数,当事件触发时该函数会被调用。第三个参数:是否在捕获阶段触发事件,需要一个布尔值,一般都传false

<body>
  <button id="btn01">点我一下</button>
</body>
</html>
<script type="text/javascript">
  window.onload = function(){
    var btn01 = document.getElementById("btn01");

    btn01.addEventListener("click",function(){
       alert(1);
     },false);

     btn01.addEventListener("click",function(){
       alert(2);
     },false);
  };
</script>

执行结果可以看到,两个绑定的响应函数都触发了,这个方法不支持IE8及以下的浏览器,但可以使用attachEvent()方法

这个方法也可以同时为一个事件绑定多个处理函数,不同的是它是后绑定先执行,执行顺序和addEventListener()相反

参数:第一个参数:事件的字符串,要on。第二个参数:回调函数

<body>
  <button id="btn01">点我一下</button>
</body>
</html>
<script type="text/javascript">
  window.onload = function(){
    var btn01 = document.getElementById("btn01");

    btn01.attachEvent("onclick",function(){
      alert(1);
    });
    btn01.attachEvent("onclick",function(){
      alert(2);
    });
    btn01.attachEvent("onclick",function(){
      alert(3);
    });
  };
</script>

执行结果是先执行了第三个绑定的响应函数,依次第二个,第一个。执行顺序和addEventListener()相反

在以上两个方法中,的this指向不一样。addEventListener()中的this,是绑定事件的对象

<body>
  <button id="btn01">点我一下</button>
</body>
</html>
<script type="text/javascript">
  window.onload = function(){
    var btn01 = document.getElementById("btn01");

    btn01.addEventListener("click",function(){
      console.log(this); // this是绑定事件的对象:<button id="btn01">点我一下</button>
    },false);
  };
</script>

attachEvent()中的this,是window

<body>
  <button id="btn01">点我一下</button>
</body>
</html>
<script type="text/javascript">
  window.onload = function(){
    var btn01 = document.getElementById("btn01");

    btn01.attachEvent("onclick",function(){
      console.log(this); //this是window
    });
  };
</script>

那么我们可以写一个方法来兼容这两种方法:先判断是否支持addEventListener方法,如果支持就执行这种方式,如果不支持就执行attachEvent方法,并且统一this的指向

<body>
  <button id="btn01">点我一下</button>
</body>
</html>
<script type="text/javascript">
  window.onload = function(){
    var btn01 = document.getElementById("btn01");

    bind(btn01 , "click" , function(){
      console.log(this);
    });
  };

  /*
   * 参数:
   *     obj 要绑定事件的对象
   *     eventStr 事件的字符串(不要on)
   *  callback 回调函数
   */
  function bind(obj , eventStr , callback){
    if(obj.addEventListener){
      //大部分浏览器兼容的方式
      obj.addEventListener(eventStr , callback , false);
    }else{
      /*
       * this是谁由调用方式决定
       * callback.call(obj)
       */
      //IE8及以下
      obj.attachEvent("on"+eventStr , function(){
        // 在匿名函数中调用回调函数
        callback.call(obj);
      });
    }
  }
</script>
原文地址:https://www.cnblogs.com/LO-ME/p/4592551.html