美文网首页
JavaScript Events事件汇总

JavaScript Events事件汇总

作者: wdapp | 来源:发表于2020-01-30 01:01 被阅读0次
    1. 事件参数、事件捕获冒泡
    2. 事件委托
    3. 事件默认行为
    4. DOM 1 、DOM 2、DOM 3模型
    5. 实现遮罩功能(点击穿透、移动端点击事件300s延迟问题)

    注意有些demo需要在开发者工具中切换PC端,移动端模拟器

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta charset="UTF-8">
      <title>事件</title>
      <style>
      * {
        margin: 0;
        padding: 0;
      }
    
      .div1 {
        width: 300px;
        height: 300px;
        border: 1px green solid;
      }
    
      .div1 .div2 {
        width: 200px;
        height: 200px;
        border: 1px green solid;
      }
    
      .div1 .div2 .div3 {
        width: 100px;
        height: 100px;
        border: 1px green solid;
      }
    
      .container {
        width: 300px;
        height: 200px;
        border: 1px black solid;
        position: relative;
      }
    
      .container .under-layer {
        width: 100%;
        height: 100%;
        background-color: pink;
      }
    
      .container .input {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 100px;
        height: 30px;
        margin-top: 20px;
        margin-left: -100px;
      }
    
      .container .popup {
        background-color: #eeeeee;
        width: 100px;
        height: 100px;
        position: absolute;
        left: 50%;
        top: 50%;
        margin-top: -50px;
        margin-left: -50px;
        z-index: 1;
        display: none;
      }
    
      .container .popup .layer-title {
        text-align: center;
        margin-top: 20px;
      }
    
      .container .popup .layer-action {
        text-align: center;
        margin-top: 20px;
      }
    
      .container .popup .layer-action .btn {
        background-color: #0A98D5;
        color: white;
        width: 60px;
        height: 30px;
      }
    
      .bg-mask {
        position: fixed;
        width: 100%;
        height: 100%;
        top: 0;
        background-color: rgba(0, 0, 0, 0.5);
        /*pointer-events: none;*/
        display: none;
      }
    
      .entrust {
        border: 1px green solid;
      }
    
      .entrust li {
        border: 1px #0A98D5 solid;
        height: 50px;
      }
    
      .no-select {
        user-select: none;
      }
      </style>
    </head>
    <body>
    <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Event">事件参数详解</a>
    <div class="div1" id="div1">
      div1
      <div class="div2" id="div2">
        div2
        <div class="div3" id="div3">
          div3
        </div>
      </div>
    </div>
    
    <button id="showMask">显示遮罩</button>
    <div class="container">
      <div class="under-layer" id="underLayer">遮罩功能 底层元素</div>
      <input class="input" type="text">
      <div class="popup" id="popupLayer">
        <div class="layer-title">弹出层</div>
        <div class="layer-action">
          <button class="btn" id="closePopup">关闭</button>
        </div>
      </div>
    </div>
    <div class="bg-mask" id="bgMask"></div>
    
    <ul id="entrust" class="entrust">
      <li>1</li>
      <li>2</li>
      <li id="li-3">3</li>
    </ul>
    
    <p class="no-select">通过css user-select: none; 设置无法被选中</p>
    <p class="select">可以被选中</p>
    
    <p>禁止图片的默认行为</p>
    <img src="https://github.wdapp.top/github/res/images/icon/CC_144_144.png" alt="" id="img">
    
    <ul>
      <li><a href="#">禁止a便签默认行为 href="#"</a></li>
      <li><a href="javascript:void(0)">禁止a便签默认行为 href="javascript:void(0)"</a></li>
      <li><a href="javascript:;">禁止a便签默认行为 href="javascript:;"</a></li>
      <li><a href="#" onclick="onClick()">禁止a便签默认行为 οnclick="onClick()"</a></li>
      <li><a href="#" onclick="handleClick();return false;">禁止a便签默认行为 onclick="handleClick();return false;"</a></li>
      <li><a href="http://www.baidu.com" onclick="return false;">禁止a便签默认行为 onclick="return false;"</a></li>
      <li><a href="https://www.baidu.com" id="link">禁止a便签默认行为 event.preventDefault()</a></li>
    </ul>
    
    <script>
    // 1.事件参数、事件捕获冒泡
    // 2.事件委托
    // 3.事件默认行为
    // 4.DOM 1 、DOM 2、DOM 3模型
    // 5.实现遮罩功能
    
    // 1.事件参数、事件捕获冒泡
    
    var div1 = document.getElementById("div1");
    var div2 = document.getElementById("div2");
    var div3 = document.getElementById("div3");
    var img = document.getElementById("img");
    var link = document.getElementById("link");
    
    // once: ture 事件只触发一次,
    // capture: false 事件冒泡(默认)
    // capture: true 事件捕获
    div1.addEventListener("click", function(event) {
      console.log("div1", event);
      // DOM3级新增事件stopImmediatePropagation()方法来阻止事件捕获,另外此方法还可以阻止事件冒泡
      // event.stopImmediatePropagation();
      // stopPropagation()方法既可以阻止事件冒泡,也可以阻止事件捕获,也可以阻止处于目标阶段。
      // event.stopPropagation();
      // stopImmediatePropagation() 和 stopPropagation()的区别
      // 后者只会阻止冒泡或者是捕获。 但是前者除此之外还会阻止该元素的其他事件发生,但是后者就不会阻止其他事件的发生。   https://developer.mozilla.org/zh-CN/docs/Web/API/Event/stopImmediatePropagation
      // for (var key in event) {
      //   console.log("for in ", key);
      // }
    }, {
      capture: false,
      once: false
    });
    
    // useCaptrue事件捕获
    div2.addEventListener("click", function(event) {
      console.log("div2", event);
      // 禁止事件捕获
      // event.stopImmediatePropagation();
      // event.stopPropagation();
    }, false);
    
    // 默认事件冒泡
    div3.addEventListener("click", function(event) {
      // 禁止事件冒泡
      // event.stopPropagation();
      // event.cancelBubble = true
      // event.preventDefault()
      console.log("div3", event);
    }, false);
    
    div1.addEventListener("dblclick", function(e) {
      console.log("dblclick", e);
    });
    
    // 2.事件委托
    var entrust = document.getElementById("entrust");
    var li3 = document.getElementById("li-3");
    entrust.addEventListener("click", function(e) {
      console.log("entrust", e);
    });
    li3.addEventListener("click", function(e) {
      console.log("li3", e);
    });
    
    // 3. 事件默认行为
    
    // 禁止图片默认行为,并且通过设置 passive: true 禁止设置event.preventDefault()
    img.addEventListener("mousedown", function(event) {
      event.preventDefault();
    }, {
      passive: true,
      mozSystemGroup: true
    });
    
    // 禁止a便签默认行为
    link.onclick = function(e) {
      if (e && e.preventDefault) {
        e.preventDefault();
      } else {
        window.event.returnValue = false;
      }
    };
    
    function handleClick() {
      console.log("handleClick");
    }
    
    function onClick() {
      console.log("onClick");
      return false;
    }
    
    // 4.事件模型与DOM 1 、DOM 2、DOM 3模型
    
    // DOM0:不是W3C规范。
    // DOM1:开始是W3C规范。专注于HTML文档和XML文档。
    // DOM2:对DOM1增加了样式表对象模型
    // DOM3:对DOM2增加了内容模型 (DTD 、Schemas) 和文档验证。
    
    // 内联事件模型
    // html
    // <button onclick="callback()">btn</button>
    
    // javascript
    // function callback() {
    //   console.log("callback");
    // }
    
    // 脚本事件模型
    // xhr.onprogress = function() { ... }
    
    // DOM 2 事件绑定
    // target.addEventListener(type, listener, options);
    // target.addEventListener(type, listener, useCapture);
    /*
    * type 表示监听事件类型的字符串。
    * listener 当所监听的事件类型触发时,会接收到一个事件通知(实现了 Event 接口的对象)对象。listener 必须是一个实现了 EventListener 接口的对象,或者是一个函数。
    * */
    /*
    * options 可选
    *   capture:  Boolean,表示 listener 会在该类型的事件捕获阶段传播到该 EventTarget 时触发。
    *   once:  Boolean,表示 listener 在添加之后最多只调用一次。如果是 true, listener 会在其被调用之后自动移除。
    *   passive: Boolean,设置为true时,表示 listener 永远不会调用 preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。
    * */
    /*
    * useCapture  可选
    * Boolean,在DOM树中,注册了listener的元素, 是否要先于它下面的EventTarget,调用该listener。 当useCapture(设为true) 时,沿着DOM树向上冒泡的事件,不会触发listener。当一个元素嵌套了另一个元素,并且两个元素都对同一事件注册了一个处理函数时,所发生的事件冒泡和事件捕获是两种不同的事件传播方式。事件传播模式决定了元素以哪个顺序接收事件。进一步的解释可以查看 事件流 及 JavaScript Event order 文档。 如果没有指定, useCapture 默认为 false 。
    * */
    
    // 5.实现遮罩功能
    // 需求:点击按钮开启遮罩。点击遮罩时,可以关闭遮罩,并且时间可以穿透到下一层,解决移动端300s延迟问题。
    
    var showMask = document.getElementById("showMask");
    var closePopup = document.getElementById("closePopup");
    var popupLayer = document.getElementById("popupLayer");
    var bgMask = document.getElementById("bgMask");
    var underLayer = document.getElementById("underLayer");
    
    var isBgMask = true;
    showMask.addEventListener("click", function() {
      popupLayer.style.display = "block";
      bgMask.style.display = "block";
      console.log("showMask");
      isBgMask = true;
    });
    
    // PC端点击过程可以拆解为 mousedown -> mouseup -> click
    // 移动端点击过程可以拆解为 touchstart -> touchend -> 300s -> click
    // 移动端 click 存在300s延迟,为了等待确认用户行为是点击还是双击。touchstart、touchend、touchmove无延迟,click有延迟,如果touch事件后target元素消失,事件会穿透
    // 当触发 touchstart 之后等待 300s 如果隐藏 popupLayer 和 bgMask,click target 则会传递到 underLayer 上,触发 click
    
    var startTime = 0;
    var endTime = 0;
    var timeout = 0;
    bgMask.addEventListener("touchstart", function(e) {
      console.log("bgMask touchend");
      e.preventDefault();//禁止触发click事件,防止点击事件穿透
      startTime = performance.now();
      closeMask();
    });
    // bgMask.addEventListener("click", function(e) {
    //   console.log("bgMask click", e);
    // });
    underLayer.addEventListener("click", function(e) {
      endTime = performance.now();
      timeout = endTime - startTime;
      console.log("underLayer", ",endTime:" + endTime, ",startTime:" + startTime, ",timeout:" + timeout + "ms");
      // alert("underLayer" + ",endTime:" + endTime + ",startTime:" + startTime + ",timeout:" + timeout + "ms");
    });
    
    function closeMask() {
      popupLayer.style.display = "none";
      bgMask.style.display = "none";
      isBgMask = false;
    }
    
    // 解决移动端点击事件300s延迟问题
    
    // 1、禁用缩放 (chrome 和 firefox)
    // 在 chrome 和 firefox 的移动版本中,如果禁用了页面缩放,那么着 300ms 的延迟就会自动消失,具体代码如下:
    // <meta name="viewport" content="width=device-width, user-scalable=no"> 或 <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
    // 缺点:safari 上并不起作用、click事件触发还是慢
    
    // 2、使用指针事件 (IE10+)CSS 触摸 action 属性,它允许你移除特定元素或整个文档的触发延迟,而无需禁用缩放:
    // a, button, .myelements {
    //   -ms-touch-action: manipulation; /* IE10  */
    //   touch-action: manipulation;     /* IE11+ */
    // }
    
    // 3、使用 touchend 事件处理 不同于 click 和 touchstart。touchend 没有这个 300ms 的延迟,而是即时触发,你完全可以在 WebGL 或 canvase 游戏中进行实践,但是在web 页面中单单使用 touchend 并不一定靠谱.
    //  1、如果用户在两个不同元素之间触发了 touchstart 和touchend,那么 click 不会被触发 .
    //  2、如果用户触发了 touchstart,但是在touchend之前是一个长长的 touchmove 滚动, 那么 click 也不会被触发.
    // 总结:可以使用touchend加event.preventDefault(),缺点是存在兼容性问题
    
    // 4、使用fastclick.js,使用fastclick实现原理:
    // var targetElement = null;
    // document.body.addEventListener("touchstart", function() {
    //   console.log("document.body.touchstart")
    //   // 记录点击的元素
    //   targetElement = event.target;
    // });
    // document.body.addEventListener("touchend", function(event) {
    //   console.log("fastclick");
    //   // 阻止默认事件(屏蔽之后的click事件)
    //   event.preventDefault();
    //   var touch = event.changedTouches[0];
    //   // 合成click事件,并添加可跟踪属性forwardedTouchEvent
    //   var clickEvent = document.createEvent("MouseEvents");
    //   clickEvent.initMouseEvent("click", true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
    //   clickEvent.forwardedTouchEvent = true; // 自定义的
    //   targetElement.dispatchEvent(clickEvent);
    // });
    
    // 5. CSS3 的方法 虽然主要讲的是事件,但是有必要介绍一个 CSS3 的属性 —— pointer-events。
    // pointer-events:  auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit;
    // auto 默认值,鼠标或触屏事件不会穿透当前层
    // none 元素不再是target,监听的元素变成了下层的元素(如果子元素设置成 auto,点击子元素会继续监听事件)
    
    // bgMask.style.pointerEvents = "none" // PC事件穿透
    // bgMask.addEventListener("mousedown", function(e) {
    //   console.log("bgMask mousedown");
    //   isBgMask = true
    // });
    // bgMask.addEventListener("mouseup", function(e) {
    //   console.log("bgMask mouseup");
    //   startTime = performance.now();
    //   closeMask();
    // });
    //
    // document.body.addEventListener("click", function(e) {
    //   if (isBgMask) {
    //     popupLayer.style.display = "none";
    //     bgMask.style.display = "none";
    //   }
    // },true);
    
    
    // 点事事件在PC端触发顺序是 mousedown -> mousemove -> mouseup -> click
    // document.body.addEventListener("mousedown", function(e) {
    //   console.log("mousedown", e)
    // },true);
    // document.body.addEventListener("mousemove", function(e) {
    //   console.log("mousemove", e)
    // },true);
    // document.body.addEventListener("mouseup", function(e) {
    //   console.log("mouseup",e)
    // },true);
    // document.body.addEventListener("click", function(e) {
    //   console.log("click", e)
    // },true);
    
    // 点击事件在移动端的触发顺序 touchstart -> touchmove -> touchend -> click
    // document.body.addEventListener("touchstart", function(e) {
    //   console.log("touchstart", e)
    // },true);
    // document.body.addEventListener("touchmove", function(e) {
    //   console.log("touchmove", e)
    // },true);
    // document.body.addEventListener("touchend", function(e) {
    //   console.log("touchend",e)
    // },true);
    // document.body.addEventListener("click", function(e) {
    //   console.log("click", e)
    // },true);
    </script>
    
    </body>
    </html>
    
    

    相关文章

      网友评论

          本文标题:JavaScript Events事件汇总

          本文链接:https://www.haomeiwen.com/subject/kfzbthtx.html