zoukankan      html  css  js  c++  java
  • 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>
  • 相关阅读:
    SpringCloud Alibaba开篇:SpringCloud这么火,为何还要学习SpringCloud Alibaba?
    SpringBoot整合原生OpenFegin的坑(非SpringCloud)
    Git入门教程,详解Git文件的四大状态
    全世界最强的算法平台codeforces究竟有什么魅力?
    设计模式第二篇,链式方法模式
    matplotlib设置颜色、标记、线条,让你的图像更加丰富
    20行代码实现,使用Tarjan算法求解强连通分量
    深入理解SVM,详解SMO算法
    手把手教你配置git和git仓库
    设计模式 | Catalog设计模式,抵御业务方需求变动
  • 原文地址:https://www.cnblogs.com/LO-ME/p/4592551.html
Copyright © 2011-2022 走看看