js原生实现FastClick事件
来源:互联网 发布:淘宝上aj正品店铺 编辑:程序博客网 时间:2024/05/18 03:49
js原生实现FastClick事件
注明:本人学习javascript时间不长,最近一直在做web端的手机网页和微信应用,由于最近有用到类似fastclick的功能,在原来的程序中用touchstart和touchend事件模拟,现在尝试将其封装,得到了以下两种有问题的方案。分享给大家,另求大神指导
在手机端Web app开发中,click事件的300ms的延迟,会造成响应缓慢,尤其在低端机中尤为明显。而使用touchstart或者touchend事件,会和默认的滚轮事件发生冲突,这也不是我们所期望的。
所以,自己动手,丰衣足食,写了一个快速点击事件的原生js代码(考虑到web app开发的环境,我们暂时无需考虑对IE等浏览器的兼容)。
实现方法1如下:
function FastClickEvent(handler){ var fastclick = { handler : handler, bind : function(query){ var targetList = document.querySelectorAll(query); for(var i=0,len=targetList.length;i<len;i++) { targetList[i].addEventListener('touchstart',handleEvent); targetList[i].addEventListener('touchend',handleEvent); } }, unbind : function(query){ var targetList = document.querySelectorAll(query); for(var i=0,len=targetList.length;i<len;i++) { targetList[i].removeEventListener('touchstart',handleEvent); targetList[i].removeEventListener('touchend',handleEvent); } } } var touchX = 0 ,touchY = 0; function handleEvent(event){ switch(event.type) { case 'touchstart': touchX = event.touches[0].clientX; touchY = event.touches[0].clientY; break; case 'touchend': var x = event.changedTouches[0].clientX; var y = event.changedTouches[0].clientY; if(Math.abs(touchX-x)<5||Math.abs(touchY-y)<5) fastclick.handler(event); break; } }; return fastclick;};
原理:根据连续touchstart和touchend事件发生时位置的变化,来判断是否是一次点击
调用:用一个handler函数来注册一个FastClickEvent事件。然后将注册好的FastClickEvent事件,通过bind方法,绑定到对应的元素上去。如下:
var handler = function(event){ console.log(event.target.id+" fastclicked");}var fastClick = new FastClickEvent(handler);fastClick.bind("div");
这段代码,我们给所有的div元素注册了fastclick的handler事件。调用fastClick.unbind
来解除元素的绑定。
但是这段代码有一个问题,为了让handleEvent
事件能够访问到touchX
,touchY
。我采用了闭包的手法,这意味着每次new一个FastClickEvent
事件对象,都要在内存中再次注入重复的handleEvent
函数。至于重复的touchX
,touchY
,更是不必多说了。
新手求助:原本是想把handleEvent函数写到原型里,但是产生的一个问题是handleEvent(event)的this对象是windows,也就是说,我取不到touchX和touchY以及handler对象,造成访问错误。
有一种比较简单的解决思路,就是只注册一个fastClickEvent
事件,然后在处理程序中根据event.target
的实际值(即发生事件的对象上)来决定响应的内容。
但是,这意味着你必须对所有的fastclick
事件都非常熟悉。
用这种方法带来的好处在于,由于你只有一个handleEvent
函数,所以基本来说,在页面释放之前,除非是你不想再触发fastclick
事件,否则无需去解绑任何元素的fastclick
事件(即使你解绑了,内存中仍然存在该handler
函数)。而且,你可以很方便的用bind(query)
来添加任何动态生成的元素的fastclick
事件,只要你在handler
函数中已经写好相应的处理程序。
如果你想添加多个fastclick
事件,而且可能要在多个地方注册,那么也只要new一个新的FastClickEvent
对象,然后绑定到对应的元素中去就可以了。
下面,介绍一种使用EventTarget类的方法。首先看一下EventTarget
function EventTarget(){ this.handlers = {};}EventTarget.prototype = { constructor: EventTarget, addHandler : function(type,handler){ if(typeof this.handlers[type] == "undefined"){ this.handlers[type]=[]; } this.handlers[type].push(handler); }, fire : function(event){ if(!event.target){ event.target = this; } if(this.handlers[event.type] instanceof Array){ var handlers = this.handlers[event.type]; for(var i=0,len=handlers.length;i<len;i++){ handlers[i](event); } } }, removeHandler : function(type,handler){ if(this.handlers[type] instanceof Array){ var handlers = this.handlers[type]; for(var i=0,len=handler.length;i<len;i++){ if(handlers[i]==handler){ break; } } handlers.splice(i,1); } }}
这个类,是一个用来添加、移除以及实现自定义类的接口。参考《JavaScript高级程序设计第三版》P616-617
那么,如何把这个类,变成我们的fastclick事件接口呢?
定义一个全局变量,用这个变量来完成所有的fastclick事件注册、删除以及添加
var FastClick = function(){ var fastclick = new EventTarget(), touchX = 0 , touchY = 0; function handleEvent(event){ switch(event.type) { case 'touchstart': touchX = event.touches[0].clientX; touchY = event.touches[0].clientY; break; case 'touchend': var x = event.changedTouches[0].clientX; var y = event.changedTouches[0].clientY; if(Math.abs(touchX-x)<5||Math.abs(touchY-y)<5) fastclick.fire({type:'fastclick',target:event.target}); break; } }; fastclick.bind = function(query) { var targetList = document.querySelectorAll(query); for(var i=0,len=targetList.length;i<len;i++) { targetList[i].addEventListener('touchstart',handleEvent); targetList[i].addEventListener('touchend',handleEvent); } } Fastclick.unbind = function(query){ var targetList = document.querySelectorAll(query); for(var i=0,len=targetList.length;i<len;i++) { targetList[i].removeEventListener('touchstart',handleEvent); targetList[i].removeEventListener('touchend',handleEvent); } } return fastclick;}();
这个全局变量FastClick可以用来添加任意的fastclick事件。
下面来讲讲如何调用。
添加事件函数:
FastClick.addHandler('fastclick',function(event){});
删除事件函数://匿名事件无法删除
FastClick.removeHandler('fastclick',handler);
绑定元素
FastClick.bind("div");
解绑
FastClick.unbind("div");
用这个方法,同样需要我们在handler事件中对event.target做预判,因为虽然这种方法可以添加多个fastclick事件,但是,事件在执行的过程中是按顺序一个一个执行的,也就是说,可能会执行你并不想执行的函数。
带来的好处在于,可以注册多个fastclick事件,而且无需再次绑定,就可以执行了。
比如说,
FastClick.bind("div");FastClick.addHandler(handler1);FastClick.addHandler(handler2);
那么,当快速点击事件发生在任一div元素时,就会顺序执行handler1和handler2。
如果我们调用removeHandler来删除handler1或handler2,那么相应的函数就不会再执行了。
另外,需要注意的是,在handler函数中,this对象是FastClick.handlers['fastclick']
这个数组,一般情况下,我们用event.target
来获取发生事件的对象。
用这种方法,基本克服了上面方法的问题,而且,对这个对象重复new并没有多大的意义,除非你不想对event.target做预判,从而生成一大堆的FaskClick类,但这显然是不高效的。
新手求助:如何能够实现特定的元素的绑定执行的函数,也就是: 能够调用
FastClick.bind(query,handler);
实现对符合query条件的元素添加handler的fastclick事件。
以上是一天的研究成果,如有转载,请注明【转载】
另求以上两个求助问题的解决思路或方案,求高手指点
参考资料:
《JavaScript高级程序设计第三版》
【读fastclick源码有感】彻底解决tap“点透”,提升移动端点击响应速度
- js原生实现FastClick事件
- 原生js实现自定义事件
- fastclick.js
- 原生js实现下拉到底事件
- jQueryy原生js实现---hover事件
- vue.js添加一些触摸事件以及安装fastclick
- 原生js--事件类型
- js原生事件封装
- 原生js--事件类型
- JS自定义事件原生
- 原生JS事件详解
- 原生js onclick事件
- js原生事件委托
- 原生js 实现document ready事件,出自犀牛书
- 原生JS实现跨浏览器的事件处理程序
- 原生JS实现AJAX、JSONP及DOM加载完成事件
- 原生JS实现AJAX、JSONP及DOM加载完成事件
- 原生JS实现元素跟随鼠标拖动事件
- Introduction to Java Programming编程题6.1<为学生分数转换为ABCDF>
- JAVA IO流(2)
- 快速排序(Java)
- 基于Jenkins+git+gradle的android持续集成
- 1094. The Largest Generation
- js原生实现FastClick事件
- Android内存泄漏研究
- 由pcap文件提取IPv6的flow数据
- 使用确定对话框来控制循环
- App 从Windows到OS X的移植
- select @@identity
- 能力风暴机器人AS-MF2011循迹算法
- mysql双主复制
- 第三方登入和分享