zoukankan      html  css  js  c++  java
  • faskclick

        PC网页上的大部分操作都是用鼠标的,即响应的是鼠标事件,包括mousedown、mouseup、mousemove和click事件。一次点击行为,事件的触发过程为:mousedown -> mouseup -> click 三步。
    手机上没有鼠标,所以就用触摸事件去实现类似的功能。touch事件包含touchstart、touchmove、touchend,注意手机上并没有tap事件。手指触发触摸事件的过程为:touchstart -> touchmove -> touchend。
        当我们手触碰屏幕时,要过300ms左右才会触发mousedown事件,所以click事件在手机上看起来就像慢半拍一样。 为什么这么设计呢? 因为它想看看你是不是要进行双击(double tap)操作。用过Zepto或KISSY等移动端js库的人肯定对tap事件不陌生,我们做PC页面时绑定click,相应地手机页面就绑定tap。但原生的touch事件本身是没有tap的,js库里提供的tap事件都是模拟出来的。
    不应用 FastClick 的场景,如果 viewport meta 标签 中设置了 width=device-width, Android 上的 Chrome 32+ 会禁用 300ms 延时;
    <meta name="viewport" content="width=device-width, initial-scale=1">
    viewport meta 标签如果设置了 user-scalable=no,Android 上的 Chrome(所有版本)都会禁用 300ms 延迟。
     
    测试延迟情况
    XX.ontouchstart = function(){
            startTime =Date.now();
        };
    XX.ontouchend = function(){
            pre.innerHTML += ('ontouchend : ' + (Date.now() - startTime) + '
    ');
        };
    XX.onclick = function(){
            pre.innerHTML += ('click : ' + (Date.now() - startTime));
        }
    if ('addEventListener' in document) {
        document.addEventListener('DOMContentLoaded', function() {
            FastClick.attach(document.body);
        }, false);
    }
    
    //优先兼容AMD方式
    if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
      define(function() {
        return FastClick;
      });
    } else if (typeof module !== 'undefined' && module.exports) {
      //兼容commonJs风格
      module.exports = FastClick.attach;
      module.exports.FastClick = FastClick;
    } else {
      //最后兼容原生Js  
      window.FastClick = FastClick;
    } 

    核心方法

    //391-450:onTouchStart
    FastClick.prototype.onTouchStart = function(event) {
      //tapDelay默认300毫秒,点击时间差小于300毫秒,则阻止事件再次触发,阻止短时间内双击的问题
      if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
        event.preventDefault();
      }
    }
    //521-610:onTouchEnd
    if (!this.needsClick(targetElement)) {
      // 如果这不是一个需要使用原生click的元素,则屏蔽原生事件,避免触发两次click
      event.preventDefault(); 
      // 触发一次模拟的click
      this.sendClick(targetElement, event);
    }
    //294-309:sendClick(核心方法)
    //这个事件会在onTouchEnd中用到,经过一系列的判断,符合条件,调用这个模拟事件
    FastClick.prototype.sendClick = function(targetElement, event) {
      var clickEvent, touch;
      //创建一个鼠标事件
      clickEvent = document.createEvent('MouseEvents');
      //初始化鼠标事件
      clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
      //触发这个事件
      targetElement.dispatchEvent(clickEvent);
    };

    用Zepto的插件touch.js中tap事件,来解决移动浏览器中300毫秒延迟的问题。但是出现了各种击穿现象
    1. 同页面tap点击弹出弹层,弹层中也有一个button,正好重叠的时候,会出现击穿
    2. tap事件点击,页面跳转,新页面中同位置也有一个按钮,会出现击穿
    我们可以看下Zepto对 singleTap 事件的处理。见源码 136-143 行,可以看出在 touchend 响应 250ms 无操作后,则触发singleTap。
    //trigger single tap after 250ms of inactivity
    else {
      touchTimeout = setTimeout(function(){
        touchTimeout = null
        if (touch.el) touch.el.trigger('singleTap')
        touch = {}
      }, 250)
    }

    1. zepto中的 tap 通过兼听绑定在 document 上的 touch 事件来完成 tap 事件的模拟的,是通过事件冒泡实现的。在点击完成时(touchstart / touchend)的 tap 事件需要冒泡到 document 上才会触发。而在冒泡到 document 之前,手指接触和离开屏幕(touchstart / touchend)是会触发 click 事件的。
    2. 因为 click 事件有延迟(大概是300ms,为了实现safari的双击事件的设计),所以在执行完 tap 事件之后,弹出层立马就隐藏了,此时 click 事件还在延迟的 300ms 之中。当 300ms 到来的时候,click 到的其实是隐藏元素下方的元素。
    3. 如果正下方的元素有绑定 click 事件,此时便会触发,如果没有绑定 click 事件的话就当没发生。如果正下方的是 input 输入框(或是 select / radio / checkbox),点击默认 focus 而弹出输入键盘,也就出现了上面的“点透”现象。
     
     
     
  • 相关阅读:
    npm
    模块化开发
    Html input 标签
    H5 移动端布局
    Mysql指令
    php面向对象
    git指令
    css3 属性
    如何渲染数据
    angular 服务
  • 原文地址:https://www.cnblogs.com/chenlogin/p/7493791.html
Copyright © 2011-2022 走看看