Skip to content

Latest commit

 

History

History
53 lines (41 loc) · 3.97 KB

zepto-tap点透.md

File metadata and controls

53 lines (41 loc) · 3.97 KB

#zepto tap点击穿透分析而fastclick 不会点击穿透

【个人总结】 首先要明确dom-events是不支持tap事件的,

那么tap是怎么来的呢?

zepto的tap事件是通过touchstart,touchend(android 4.0.x不支持touchend,通过touchmove 设置定时器触发touched)模拟出来的,事件是绑定在document上,大体思路是在touchstart的时候向对象附加点击的x,y;(其中还包含很多细节,比如设置最后点击时间,设置长按定时器等);touchmove的过程动态的计算手势在view上的偏移点,最后touchend 根据偏移点确定是否是点击,如果是点击动态的构建一个event然后根据设置的状态获取是单机、双击。 原则上根据上边的步骤可以在m版本上做到事件的响应等,但是点穿又是如何发生的(在我们手写的业务代码中都习惯event.preventDefault();return false 等组织事件冒泡),

      if (deltaX < 30 && deltaY < 30) {
        // delay by one tick so we can cancel the 'tap' event if 'scroll' fires
        // ('tap' fires before 'scroll')
        tapTimeout = setTimeout(function() {

          // trigger universal 'tap' with the option to cancelTouch()
          // (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
          var event = $.Event('tap')
          event.cancelTouch = cancelAll
          touch.el.trigger(event)

          // trigger double tap immediately
          if (touch.isDoubleTap) {
            if (touch.el) touch.el.trigger('doubleTap')
            touch = {}
          }

          // trigger single tap after 250ms of inactivity
          else {
            touchTimeout = setTimeout(function(){
              touchTimeout = null
              if (touch.el) touch.el.trigger('singleTap')
              touch = {}
            }, 250)
          }
        }, 0)
      } else {
        touch = {}
      }
      deltaX = deltaY = 0

看到如下代码,你会发现,tap是通过setTimeout ,定时器的代码在js引擎执行的优先级低,会等待当前没有在执行的时候才会触发,这样算是我们阻止冒泡依旧会造成点透的问题。

那么fastClick又是怎么做到的呢? 今天头疼脑大的读了一下fastClick的代码,大概看了一下它的流程(当然理解也会存在偏差),大致分析一下fastClick的流程,状态什么的设定就不说了,fastClick事件绑定在初始化设定的dom上,初始化流程

FastClick.attach = function(layer, options) {
	return new FastClick(layer, options);
};

然后内部绑定touch*, click,mouse* 相关的事件,判断是否有stopImmediatePropagation(如果这个函数会取消dom绑定函数队列中在其后绑定事件执行)函数进行事件监听重写 dom的click事件是通过touchend的去触发(原生的click会比touch事件晚200-300ms),这样就然让click的事件响应提快,那么touchend又如何防止点透呢(内部包含很多平台差异的处理不说了,有些我也遇见过),因为事件绑定到初始化设定的dom,在touchend的时候获取到它的触发目标,内部在sendClik的时候判断冒泡的元素是否可以[focus,click],然后每一个可点击的目标对应触发sendClick(内部判断是不是触发源,如果是就创建一个mouseEvent事件然后手动触发);不是的话就return false;(在我看来内部绑定的onclick除了在touchend不触发的设备上会响应,其他的时候都应该是通过touchend去触发的)。【总觉得写的很乱,一句话说明zepto可点透跟设置定时器去触发有关,就算是阻止默认行为也没不行,fastClick 则是通过touchend触发click,然后内部确定是否是触发源,如果不是blur,如果是则创建event手动触发】,当然内部的触发界定(例如时间,像素这类的)没有说。