• JS DOM2级事件兼容处理


    DOM2级事件兼容处理

    THIS问题

    bindDOM2():

    在IE6~8中使用attachEvent绑定事件的时候,因为不支持bind方法,所以不能用bind方法解决。

     var tempFn = function () {
              eventFn.call(curEle);
    };
    

    通过在外层包括一个化妆函数,调用这个化妆函数时调用需要绑定的函数.call(curEle),并为这个化妆函数增加一个photo属性用于保存化妆之前的函数,便于删除的时候对比函数。

    tempFn.photo = eventFn;
    
    

    为当前元素创建一个自定义属性“myBind”+ evenType,它保存当前元素对应事件类型绑定的化妆函数,以便后期清除。

    if (!curEle["myBind" + evenType]) {
              curEle["myBind" + evenType] = [];
            }
            curEle["myBind" + evenType].push(tempFn);
            curEle.attachEvent("on" + eventType, tempFn);
    

    unbindDOM2():

    通过当前元素的“myBind”属性找到绑定的化妆函数,对比化妆函数.photo确定是不是这个要移除这个化妆后的函数,找到后把事件和化妆函数移除掉。

     var ary = curEle["myBind" + evenType];
            for (var i = 0; i < ary.length; i++) {
              if (ary[i].photo === eventFn) {
                ary.splice(i, 1);
                curEle.detachEvent("on" + evenType, ary[i]);
                break;
              }
            }
    

    重复问题

    bindDOM2():

    上面实现的bindDOM2(),可以想同一个元素中同一个行为添加相同的事件函数,存在重复问题。

    每一次自己在往自定义属性对应的容器中添加前,看一下之前是否已经有了,有的话就不用再重新的添加了,同理也不需要再往事件池中存储了

    var ary = curEle["myBind" + eventType];
            for (var i = 0; i < ary.length; i++) {
              var cur = ary[i];
              if (cur.photo === eventFn) {
                return;
              }
            }
    

    unbindDOM2():

    顺序问题

    bindDOM2():

    不用浏览器自带的事件池,而是自己模拟标准浏览器的事件池
    自己创建一个事件池,把需要触发的函数按顺序放到事件池中。为当前元素绑定一个run方法,当run方法执行的时候去事件池中获取同类型的方法数组。然后依次执行这些方法,执行的时候使用call(HTMLElement,e)使THIS指向触发元素,使方法的一个参数变为处理后的window.event。

    // run: 我们只给当前元素的带年纪行为绑定一个方法run,当点击事件执行的时候执行的是run方法,我在run方法中根据自己存储的方法顺序分别的再把这些方法执行
          function run(e) {
            e = e || window.event;
            var flag = e.target ? true : false; // IE6~8下不兼容e.target,得到的flag为false
            if (!flag) {
              e.target = e.srcElement;
              e.pageX =
                e.clientX +
                (document.documentElement.scrollLeft || doucment.body.scrollLeft);
              e.pageY =
                e.clientY +
                (document.documentElement.scrollTop || doucment.body.scrollTop);
              e.preventDefault = function () {
                e.returnValue = false;
              };
              e.stopPropagation = function () {
                e.cancelBubble = true;
              };
            }
            // this:当前点击的这个元素curEle  e.target存储的是当前触发的元素curEle
            // 获取自己事件池中绑定的那些方法,并且让这些方法依次的执行
            var ary = e.target["myEvent" + e.type];
            for (var i = 0; i < ary.length; i++) {
              var tempFn = ary[i];
              tempFn.call(this, e);
            }
          }
    

    unbindDOM2():

    function off(curEle, eventType, eventFn) {
            var ary = curEle["myEvent" + eventType];
            for (var i = 0; i < ary.length; i++) {
              var cur = ary[i];
              if (cur === eventFn) {
                ary.splice(i, 1);
              }
            }
          }
    

    整个代码

    <!--
     * @Author: lemon
     * @Date: 2020-09-17 15:15:13
     * @LastEditTime: 2020-09-17 17:58:04
     * @LastEditors: Please set LastEditors
     * @Description: In User Settings Edit
     * @FilePath: React前端准备事件DOM2事件.html
    -->
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style type="text/css">
          * {
            margin: 0;
            padding: 0;
          }
          #box {
            margin: 20px auto;
             200px;
            height: 200px;
            background: lightblue;
          }
        </style>
      </head>
      <body>
        <div id="box"></div>
        <script type="text/javascript">
          var box = document.getElementById("box");
          function con() {
            console.log(this);
          }
          box.addEventListener("click", con, false);
          box.removeEventListener("click", con, false);
          // 处理DOM2级事件绑定的兼容性问题(绑定方法)
          function bindDOM2(curEle, evenType, eventFn) {
            if ("addEventListener" in document) {
              curEle.addEventListener(evenType, eventFn, false);
              return;
            }
            // eventFn化妆,并且把化妆前的照片贴在自己对应的脑门上
            var tempFn = function () {
              eventFn.call(curEle);
            };
            tempFn.photo = eventFn;
            if (!curEle["myBind" + evenType]) {
              curEle["myBind" + evenType] = [];
            }
            // 解决重复问题:每一次自己在往自定义属性对应的容器中添加前,看一下之前是否已经有了,有的话就不用再重新的添加了,同理也不需要再往事件池中存储了
            var ary = curEle["myBind" + eventType];
            for (var i = 0; i < ary.length; i++) {
              var cur = ary[i];
              if (cur.photo === eventFn) {
                return;
              }
            }
            curEle["myBind" + evenType].push(tempFn);
            curEle.attachEvent("on" + eventType, tempFn);
          }
          function unbindDom2(curEle, eventType, eventFn) {
            if ("removeEventListener" in document) {
              curEle.removeEventListener(eventType, eventFn, false);
              return;
            }
            var ary = curEle["myBind" + evenType];
            for (var i = 0; i < ary.length; i++) {
              if (ary[i].photo === eventFn) {
                ary.splice(i, 1);
                curEle.detachEvent("on" + evenType, ary[i]);
                break;
              }
            }
          }
          // on:创建事件池,并且把需要给当前元素绑定的方法依次的增加到事件池中
          function on(curEle, evenType, eventFn) {
            if (!curEle["myEvent" + evenType]) {
              curEle["myEvent" + evenType] = [];
            }
            var ary = curEle["myEvent" + evenType];
            for (var i = 0; i < ary.length; ++i) {
              var cur = ary[i];
              if (cur === eventFn) {
                return;
              }
            }
            ary.push(eventFn);
            // 执行on的时候, 我们给当前元素绑定了一个点击的行为,当点击得时候执行run方法:
            // run方法中的this是当前元素curEle, 并且浏览器给run传递了一个MouseEvent对象
            bindDOM2(curEle, eventType, run);
          }
          // off:在自己的事件池中把某一个方法移除
          function off(curEle, eventType, eventFn) {
            var ary = curEle["myEvent" + eventType];
            for (var i = 0; i < ary.length; i++) {
              var cur = ary[i];
              if (cur === eventFn) {
                ary.splice(i, 1);
              }
            }
          }
          // run: 我们只给当前元素的带年纪行为绑定一个方法run,当点击事件执行的时候执行的是run方法,我在run方法中根据自己存储的方法顺序分别的再把这些方法执行
          function run(e) {
            e = e || window.event;
            var flag = e.target ? true : false; // IE6~8下不兼容e.target,得到的flag为false
            if (!flag) {
              e.target = e.srcElement;
              e.pageX =
                e.clientX +
                (document.documentElement.scrollLeft || doucment.body.scrollLeft);
              e.pageY =
                e.clientY +
                (document.documentElement.scrollTop || doucment.body.scrollTop);
              e.preventDefault = function () {
                e.returnValue = false;
              };
              e.stopPropagation = function () {
                e.cancelBubble = true;
              };
            }
            // this:当前点击的这个元素curEle  e.target存储的是当前触发的元素curEle
            // 获取自己事件池中绑定的那些方法,并且让这些方法依次的执行
            var ary = e.target["myEvent" + e.type];
            for (var i = 0; i < ary.length; i++) {
              var tempFn = ary[i];
              tempFn.call(this, e);
            }
          }
        </script>
      </body>
    </html>
    
  • 相关阅读:
    ASP.NET Core 返回 Json DateTime 格式
    IdentityServer4 SigningCredential(RSA 证书加密)
    IdentityServer4 指定角色授权(Authorize(Roles="admin"))
    ASP.NET Core 指定环境发布(hosting environment)
    ASP.NET Core 使用 Redis 客户端
    IdentityServer4 实现 OAuth 2.0(密码模式
    IdentityServer4 登录成功后,跳转到原来页面
    IdentityServer4 退出登录后,跳转到原来页面
    C#面向插件级别的软件开发
    使用XML序列化实现系统配置
  • 原文地址:https://www.cnblogs.com/xiaoxu-xmy/p/13686602.html
Copyright © 2020-2023  润新知