实现tap的多种方式

简介: 这是一个比较轻量的插件tap.js,142行代码,支持模块化开发。

一、tap.js


这是一个比较轻量的插件tap.js,142行代码,支持模块化开发。


1)handleEvent


addEventListener方法中的第二个参数,我原先并没有注意到其实可以传一个对象,该对象必是实现EventListener接口,查看在线代码


var tap = {
  handleEvent: function() {
    alert(this.name);
  },
  name:'tap'
};
document.getElementById('button').addEventListener('click', tap, false);


这样一绑定点击就能alert了。并且注意上面的“this”,“this”指向的是“tap”这个对象,而不是这个方法。这种写法有几种好处:

1. 可以使用“tap”对象中的属性或方法了。

2. 动态地改变事件处理器,例如tap.handleEvent = xx.yy,而不用先removeEventListeneraddEventListener了。

在插件的129行定义了“Tap.prototype.handleEvent”,在这个方法中通过“switch(e.type)”执行不同的事件。

 

2)自定义事件


插件中使用了两种方式创建自定义事件,新方式CustomEvent与旧方式createEvent查看在线代码

1. CustomEvent


//CustomEvent方式
var tap2 = document.getElementById('button2');
tap2.addEventListener('tap', function(e){
  alert('custom ' + e.detail);
}, false);
var evt = new window.CustomEvent('tap', {
  bubbles: true,
  cancelable: true,
  detail: 'tap'
});
tap2.dispatchEvent(evt);


“button2”就是个按钮,绑定了个tap事件,注意不是绑定了这个后,点击按钮就会出现alert内容,如果想要点击,还是需要绑定“click”事件的。

“detail”参数是指当事件初始化时传递的数据,可以传递任何值,“tap2.dispatchEvent()”方法返回一个布尔值

如果想点击按钮触发“tap”事件,可以下面这样做:


tap2.addEventListener('click', function(e){
  tap2.dispatchEvent(evt);
}, false);


2. createEvent


var evt = document.createEvent('Event');
evt.initEvent('tap', true, true);


就创建自定义事件部分不一样,其他地方都差不多。

插件在“Tap.prototype.end”方法中定义了事件,90行到108行。

 

3)使用方式


插件的prototype总共有方法“leftButton”、“start”、“move”、“end”、“cancel”、“destroy”和“handleEvent”。下面是demo代码:

<div id="container">
  <button id="button-1">Tap event</button>
</div>
<script>
    var container = document.getElementById('container');
    var button1 = document.getElementById('button-1');
    var tap = new Tap(container);//创建tap对象
    button1.addEventListener('tap', callback, false);
    function callback (e) {
        e.preventDefault();
        console.log('event: ' + e.type);
    }
</script>


在PC上面使用,通过“mousedown”、“mousemove”与“mouseup”来模拟。

在移动端使用,是通过“touchstart”、“touchmove”、“touchend”与“touchcancel”来模拟。


1. tap构造函数


在“tap”构造函数中绑定了“touchstart”和“mousedown”事件,上面点击按钮产生的效果,其实是通过点击“container”来实现的。


function Tap(el) {
  this.el = typeof el === 'object' ? el : document.getElementById(el);
  this.moved = false; //flags if the finger has moved
  this.startX = 0; //starting x coordinate
  this.startY = 0; //starting y coordinate
  this.hasTouchEventOccured = false; //flag touch event
  this.el.addEventListener('touchstart', this, false);
  this.el.addEventListener('mousedown', this, false);
}


2. 事件处理方法“handleEvent”

上面的“this.el.addEventListener('touchstart', this, false); ”就用到了handleEvent概念来执行事件。


Tap.prototype.handleEvent = function(e) {
  switch (e.type) {
    case 'touchstart':this.start(e);break;
    case 'touchmove':this.move(e);break;
    case 'touchend':this.end(e);break;
    case 'touchcancel':this.cancel(e);break;
    case 'mousedown':this.start(e);break;
    case 'mouseup':this.end(e);break;
    case 'mousemove':this.move(e);break;
  }
};


3. 触发“tap”

在前面《触屏touch事件记录》中讲到过,“touchstart”与“touchend”会成对出现,那么就会触发插件中的“end”方法。而end方式就是执行“tap”的关键地方。


if (!this.moved) {
  try {
    evt = new window.CustomEvent('tap', {
      bubbles: true,
      cancelable: true
    });
  } catch (e) {
    evt = document.createEvent('Event');
    evt.initEvent('tap', true, true);
  }
  e.stopPropagation();
  if (!e.target.dispatchEvent(evt)) {
    e.preventDefault();
  }
}


用到了自定义事件的概念,“e.target.dispatchEvent(evt)”这句判断可以执行“e.preventDefault()”,这个地方可以有效的阻止“click”事件的发生,防止“点透”。

 

二、Zepto中的touch.js


Zepto是一个轻量级的针对现代高级浏览器的JavaScript库, 它与jquery有着类似的api。而touch.js是其一个扩展包,用于操作移动端的相关手势事件,兼容IOS、Android与Windows Phone。


1)Windows Phone指针事件


在源码中有两套Windows的指针事件,IE10中的MSPointerDown、MSPointerMove、MSPointerUp、MSPointerCancel与IE11中的pointerdown、pointermove、pointerup、pointercancel。

自 IE11 起,Microsoft 前缀版本的指针事件 API 不再受支持,查看指针事件指针事件更新


37.jpg


2)原理


tap.js不同,它是将事件绑定在document中,并且比tap.js更完善,有长按,双击,上下左右划屏等,代码长度也就100多行。

与tap.js一样也是在touchend中自定义了“tap”事件,从touch.js中的119行开始。与tap.js一样,也有X和Y的偏移距离判断,这里是30以内,tap.js是10以内。


if (deltaX < 30 && deltaY < 30) {
  tapTimeout = setTimeout(function() {
    var event = $.Event('tap')
    event.cancelTouch = cancelAll
    touch.el.trigger(event)
    if (touch.isDoubleTap) {
      if (touch.el) touch.el.trigger('doubleTap')
      touch = {}
    }else {
      touchTimeout = setTimeout(function() {
        touchTimeout = null
        if (touch.el) touch.el.trigger('singleTap')
        touch = {}
      }, 250)
    }
  }, 0);
}


上面代码中3、4、5就是在执行“tap”事件了,而7-16行代码是在执行双击或单击。从上面的代码中可以看出,会出现点透,因为并没有阻止“click”事件的执行。


<div class="outter" id="outter"></div>
<div class="layer" id="layer"></div>
<script>
  $('#layer').on('tap', function() {
    var $this = $(this);
    $this.hide();
  });
  $('#outter').on('click', function() {
    alert('点透');
  });
</script>


测试了下在UC中并没有出现点透,但是在微信浏览器中出现了。如下图所示,我点击橙色区域,会触发层下面绑定的“click”事件。


0.gif


3)解决方法

1. 第一种有点暴力,既然没有阻止默认行为,那我就在最后加一个阻止。


if (deltaX < 30 && deltaY < 30) {
  //.....
  e.preventDefault();
}


2. 第二种是在“tap”事件中做个异步,延迟300ms后再触发,这样的话“click”事件已经触发了。


$('#layer').on('tap', function() {
  var $this = $(this);
  setTimeout(function() {
    $this.hide();
  }, 300);
});


三、Hammer.js实现tap


如果说tap.js是点心,touch.js是简餐,那么hammer.js就是大餐了。2569行代码,兼容各种浏览器,包括移动与PC端。

浏览器兼容性如下,查看更多兼容性


38.jpg


实现的代码中封装了很多的逻辑,最后是将逻辑绑定到了“touchend”中,“touchstart”也绑定了,但是只执行了“touchend”事件。

关于这个插件的分析,篇幅比较长,可以参考《Hammer.js分析》的几篇文章。

 

相关文章
|
7月前
|
小程序 JavaScript
【微信小程序】-- WXML 模板语法 - 事件绑定 -- tap & input (十)
【微信小程序】-- WXML 模板语法 - 事件绑定 -- tap & input (十)
uni-app事件冒泡 如何解决事件冒泡 推荐tap事件
uni-app事件冒泡 如何解决事件冒泡 推荐tap事件
|
7月前
移动端click事件、touch事件、tap事件的区别
移动端click事件、touch事件、tap事件的区别
227 0
|
3月前
Twaver-HTML5基础学习(30)监听事件_network绘制监听_network视图操作监听_鼠标事件的监听
本文介绍了如何在Twaver-HTML5中监听网络视图操作事件,包括视图绘制、鼠标事件以及获取鼠标下的网元等。
43 1
Twaver-HTML5基础学习(30)监听事件_network绘制监听_network视图操作监听_鼠标事件的监听
|
7月前
|
开发者
移动端 click 事件、touch 事件、tap 事件的区别
移动端 click 事件、touch 事件、tap 事件的区别
34 1
21avalon - 指令ms-hover(hover绑定)
21avalon - 指令ms-hover(hover绑定)
48 0
35avalon - 指令ms-widget(组件绑定介绍)
35avalon - 指令ms-widget(组件绑定介绍)
33 0
|
JavaScript
Vue antdv dropdown 自定义下拉内容 overlay 禁止点击事件下传导致收起
Vue antdv dropdown 自定义下拉内容 overlay 禁止点击事件下传导致收起
360 0
|
Java Android开发 C++
Framework 全局监听屏幕点击事件 INPUT_EVENT_INJECTION
Framework 全局监听屏幕点击事件 INPUT_EVENT_INJECTION
322 0
lodash的tap操作
lodash的tap操作
92 0