实现tap的多种方式
一、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,而不用先removeEventListener再addEventListener了。
在插件的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 不再受支持,查看指针事件,指针事件更新。

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”事件。

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端。
浏览器兼容性如下,查看更多兼容性。

实现的代码中封装了很多的逻辑,最后是将逻辑绑定到了“touchend”中,“touchstart”也绑定了,但是只执行了“touchend”事件。
关于这个插件的分析,篇幅比较长,可以参考《Hammer.js分析》的几篇文章。
demo源码下载:
http://download.csdn.net/download/loneleaf1/9429374
参考资料:
http://www.ayqy.net/blog/handleevent%E4%B8%8Eaddeventlistener/ handleEvent与addEventListener
https://github.com/memoryza/--/blob/master/zepto-tap%E7%82%B9%E9%80%8F.md zepto tap点击穿透分析
实现tap的多种方式的更多相关文章
- idea打包jar的多种方式
这里总结出用IDEA打包jar包的多种方式,以后的项目打包Jar包可以参考如下形式: 用IDEA自带的打包形式 用Maven插件maven-shade-plugin打包 用Maven插件maven-a ...
- Java中测试异常的多种方式
使用JUnit来测试Java代码中的异常有很多种方式,你知道几种? 给定这样一个class. Person.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...
- Spring学习总结(一)——Spring实现IoC的多种方式
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法.没有IoC的程序中我们使用面向对象编程对象的创 ...
- PDO多种方式取得查询结果
PDO多种方式取得查询结果 01 December 2009 1:26 Tuesday by Sjolzy PDO最大的特点之一是它的灵活性,本节将介绍如何取得查询结果,包括: 数组(数值或关联数组) ...
- java 获取classpath下文件多种方式
java 获取classpath下文件多种方式 一:properties下配置 在resources下定义server.properties register.jks.path=classpath\: ...
- IOC和AOP使用扩展 多种方式实现依赖注入
多种方式实现依赖注入 1.Spring 使用setter访问器实现对属性的赋值, 2.Spring 构造constructor方法赋值, 3.接口注入 4.Spring P命名空间注入直接量 sett ...
- sql语句分页多种方式ROW_NUMBER()OVER
sql语句分页多种方式ROW_NUMBER()OVER 摘自: http://www.cnblogs.com/CodingArt/articles/1692468.html 方式一 select to ...
- JavaScript中判断为整数的多种方式
之前记录过JavaScript中判断为数字类型的多种方式,这篇看看如何判断为整数类型(Integer). JavaScript中不区分整数和浮点数,所有数字内部都采用64位浮点格式表示,和Java的d ...
- 使用多种方式实现遍历HashMap
今天讲解的主要是使用多种方式来实现遍历HashMap取出Key和value,首先在java中如果想让一个集合能够用for增强来实现迭代,那么此接口或类必须实现Iterable接口,那么Iterable ...
随机推荐
- 新手 gulp+ seajs 小demo
首先,不说废话,它的介绍和作者就不在多说了,网上一百度一大堆: 我在这里只是来写写我这2天抽空对seajs的了解并爬过的坑,和实现的一个小demo(纯属为了实现,高手请绕道); 一.环境工具及安装 1 ...
- Matlab 视频与图像之间的相互转换
matlab版本是2015b,其中更新了部分函数库之前网上相关程序不适用于新版本,在此提供适用于新版本的程序: 帧序列转换为视频 function video = frames2video(frame ...
- 安卓刷机--fastboot线刷
首先需要下载fastboot.exe,copy到system32文件夹下. 对于安卓系统的智能手机,同时按住开机键和音量减键,或手机连上电脑,输入adb reboot bootloader进入fast ...
- 解读ASP.NET 5 & MVC6系列
本系列的大部分内容来自于微软源码的阅读和网络,大部分测试代码都是基于VS RC版本进行测试的. 解读ASP.NET 5 & MVC6系列(1):ASP.NET 5简介 解读ASP.NET 5 ...
- HTML5- Canvas入门(六)
已经第六章了,也差不多接近尾声,如果你从第一章耐心follow到本章结束,那你便能掌握canvas的大部分知识点(当然如果要精通,还是得多靠练习,做一些小案例). 今天我们要学习的是canvas的变形 ...
- HTML5- Canvas入门(二)
上篇文章我们了解了canvas的定义.获取和基础的绘图操作,其中的绘图功能我们讲解了线段绘制.上色.描边等方面知识点. 今天我们来讲讲矩形(Rectangle)和多边形的绘制. 矩形的绘制一共有两个口 ...
- Net作业调度(二) -CrystalQuartz远程管理
Source Code-1.6M 介绍 上篇已经了解Quartz.NET的基本使用方法了.但如果想方便的知道某个作业执行情况,需要暂停,启动等操作行为,这时候就需要个Job管理的界面. 本文介绍Qua ...
- C++高精度计时器——微秒级时间统计
在C++中,经常需要通过计时来统计性能信息,通过统计的耗时信息,来分析性能瓶颈,通常情况下,可能毫秒级别的时间统计就足够用了,但是在毫厘必争的性能热点的地方,毫秒级别的统计还是不够的,这种情况下,就需 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (36) ------ 第六章 继承与建模高级应用之TPC继承映射
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-12 TPC继承映射建模 问题 你有两张或多张架构和数据类似的表,你想使用TP ...
- windows命令——explorer
转至http://www.cnblogs.com/ymind/archive/2012/03/30/explorer-command-args.html 今天才知道,explorer原来可以这样用, ...