一、事件捕获与冒泡

先扯一下事件的触发流程,这个之后会用到。

DOM2级事件规定事件包括三个阶段:

① 事件捕获阶段

② 处于目标阶段

③ 事件冒泡阶段

大概的流程就是事件从最外层一层一层往里面传递(捕获阶段), 到达触发事件的目标元素(目标阶段),然后再一层一层往上冒泡(冒泡阶段)。这个流程事件所经过的元素绑定的对应事件的侦听器都会被触发。例如对元素p的子元素c绑定点击事件,点击元素c后会先在p触发点击事件,使用dispatch触发也是。

PS:事件侦听通过target.addEventListener(type, listener[, useCapture])添加,useCapture参数代表是否在捕获阶段触发事件。

二、click事件的300ms延迟

移动设备中使用click事件和在PC端会有所不同,大多数基于触摸的浏览器设备,在点击时都会有个300ms的事件触发等待时间,原因在于单击后面还有个双击缩放动作,这个涉及到触摸设备的手势交互行为原生设计,设备需要通过时间判断是单击还是双击。

对于这300ms的延迟,根据网上搜索的资料,可通过几个简单的方法解决:

  1. 无视之。。。如果所涉及业务对点击的反应时间要求不大,300ms其实是可以忽略的。
  2. 在 chrome 和 firefox 的移动版本中,禁用页面缩放可消除该延迟。不过只兼容这两种不好。
  3. 在 chrome 32+ 中,设置 viewport 的宽度小于或等于物理设备的宽度。因为只支持chrome 32+,所以也忽略。
  4. IE10+中设置CSS触摸 action 属性。以后其他浏览器可能也会支持。但目前只支持IE10+,所以也忽略。
  5. 使用touch事件而不是click事件。这样必须可以解决延迟,但也因此引发了奇怪的问题,由此转入正文。

三、zepto的tap事件

如果我们直接使用touchend事件来代替click事件,一个很明显的不妥就是如果滑动到某个元素上放开手那么就会触发该元素的touchend事件,这明显不跟点击操作一致。另外一个问题即触发touchend事件后,在该区域300ms后还会触发一次click事件,如果一个元素touchend后消失,那么其点击区域底下的元素还会被触发一次click事件,这个问题叫做点透,不过这可以通过event.preventDefault来阻止(默认行为)。

为了更好的模拟点击事件并解决移动设备点击的300ms延迟,zepto的touch模块自定义了一个tap事件,该事件原理即是使用touch事件来模拟的。基本原理就是给元素绑定touchstart和touchend事件,然后判断前后事件的触发区域是否一致,是的话即触发自定义的点击事件。

看起来挺完美的,但事实上使用zepto的tap事件即使在事件回调函数中使用了preventDefault还是会出现点透问题。究其原因,就是zepto在触发事件的时候使用了定时器。在自定义事件被触发之前默认行为早就发生了,因此阻止不了click事件的触发。

暂时不管zepto,对于click事件,我们可以用另外一个插件提高click事件的响应速度,这就是fastclick!

四、fastclick

Fastclick的基本思想就是在某个父元素上捕获其子元素的touchstart与touchend事件,然后依然根据位置信息判断是否为点击动作,如果是的话立即使用dispatchEvent手动派发子元素的click事件,从而缩短了响应事件,并且在touchend的时候使用preventDefault阻止默认事件,防止300ms后再次触发click事件。

事情貌似就这么解决了,但事实就是没这么完美。撇开手动派发事件带来的性能损耗不说,在android上preventDefault阻止touchend触发click事件还没有用,即在android上只要使用了touchend,就一定会触发click事件,翻阅了很多资料后发现这个问题无法解决,有人说touchstart的时候调用preventDefault可阻止click,但亲测过不行。

这时候,就只能用比较猥琐的方法来解决了。在fastclick判断为点击操作并触发click事件时,我们给事件对象添加一个flag。从之前的内容可以得知click事件会先在外层容器上触发,因此我们在根目录上侦听click事件,当事件对象存在flag时即不做操作,当不存在时即阻止其事件派发流程。这样即元素绑定在元素上的点击事件侦听器只会被手动触发的click事件触发。

document.addEventListener('click', function (event) {

         if (event.myclick == true) {

          return true;

         }

         if (event.stopImmediatePropagation) {

          event.stopImmediatePropagation();

         } else {

          event.propagationStopped = true;

         }

         event.stopPropagation();

         event.preventDefault();

         return true;

}, true);

虽然使用fastclick可以解决click的延迟问题,但添加了许多额外的操作,性能上的损耗是无可避免的。因此如果对点击操作的要求不是很高的话还是建议忽略那点延迟。

 

移动页面click延迟引发的touch问题的更多相关文章

  1. JS click延迟解决方案

    click延迟解决方案     移动端click事件会有300ms的延迟,原因是移动端屏幕双击会缩放页面 1.禁止缩放功能 浏览器禁用默认双击缩放行为去掉300ms的点击延迟 user-scalabl ...

  2. 聊聊click延迟和点击穿透

    博客原文地址:Claiyre的个人博客 https://claiyre.github.io/ 如需转载,请在文章开头注明原文地址 移动端click事件被延迟 移动端的开发经常需要监听用户的双击行为,所 ...

  3. zepto的touch模块解决click延迟300ms问题以及点透问题的详解

    大家都知道移动端的click事件会延迟300ms触发,这时大家可以使用zepto的touch模块,里面定义了一个tap事件,通过绑定tap事件,可以实现点击立即触发的功能. 那么,它的tap事件是怎么 ...

  4. 移动端click延迟和tap事件

    一.click等事件在移动端的延迟 click事件在移动端和pc端均可以触发,但是在移动端有延迟现象. 1.背景 由于早期移动设备浏览网页时内容较小,为了增强用户体验,苹果公司专门为移动设备设计了双击 ...

  5. AlloyTouch Button插件-不再愁click延迟和点击态

    移动端不能使用click,因为click会有300ms.所有有了fastclick这样的解决方案.然后fastclick并没有解决点击态(用户点击的瞬间要有及时的外观变化反馈)的问题.hover会有不 ...

  6. 开发移动端web页面click事件失效问题

    这两天在做一个WAP页面,在chrome上模拟移动端的时候,都好好的,然而放到手机上测试时, 发现有些点击事件直接无反应,但是有些有反应: 难道是由于我页面上有用到滚动插件,里面的touch事件的pr ...

  7. 由单页面web应用引发的企业应用问题

    由于单页面web应用的流行,client与server端之间都对应的产生了一些微妙的变化,比方,client原来仅仅是用来展示页面和理清逻辑,而现在逐渐转变成了一个可以进入驱动状态的应用程序. 未来的 ...

  8. javascript js 完美解决 click 与 dblclick 冲突,并且不会导致click延迟

    示例代码: marker.addEventListener("click", function(){ if (!window.markerClicked) { window.mar ...

  9. bug:页面交互操作引发的问题

    最近在测试一些h5页面,突然悟到一些测试点 需求点: 用户可以在页面领取礼物,领取的礼物在页面底部展示,用户点击礼物可调起分享弹窗,礼物超过一屏可左右滑动, bug的表现形式: 仅当礼物超过一屏时(一 ...

随机推荐

  1. Fata7y Ya Warda! SPOJ - DRUIDEOI 单调栈

    题意:1e5个数围成一个环.现在要输出每个数左右第一个大于它的数的下标.若没有,则输出-1. 题解:单调栈板题.只是要把数据压入栈压两遍来模仿环.    具体分析:考虑一个递减的数列.要找左边最大的 ...

  2. Elasticsearch 的坑爹事——记录一次mapping field修改过程(转)

    原文:http://www.cnblogs.com/Creator/p/3722408.html 本文记录一次Elasticsearch mapping field修改过程 团队使用Elasticse ...

  3. Elasticsearch教程-从入门到精通(转)

    原文:http://mageedu.blog.51cto.com/4265610/1714522?utm_source=tuicool&utm_medium=referral 各位运维同行朋友 ...

  4. 第一课 JDK环境变量配置

    第一步:下载,并解压到D:/JDK 第二步:环境变量配置 右键我的电脑->属性->高级->环境变量->系统变量(注意:是下面的系统变量,不是上面的用户变量) 新建变量名 JAV ...

  5. android奔溃日期一闪而过

    Android Studio日期崩溃了一闪而过,看不到原因:可以设置No Filters就可以了

  6. MySQL字符集设置及字符转换(latin1转utf8)

    MySQL字符集设置及字符转换(latin1转utf8) http://blog.chinaunix.net/uid-25266990-id-3344584.html  MySQL字符集设置及字符转换 ...

  7. [py][mx]xadmin详细设置-将app注册到xadmin

    首先createsuperuser,创建用户, 然后登陆xadmin. 理解下models的各个字段 复数形式及返回 注册app users/adminx.py 显示字段 users/adminx.p ...

  8. [py]letcode第一题求和

    letcode第一题, tm的不好弄. 想了很久想到了一个粗蠢的解决办法. Given an array of integers, return indices of the two numbers ...

  9. UMI标签学习【转载】

    转自: https://club.1688.com/threadview/50123159.htm 简单介绍一下利用单分子标签(Unique Molecular Identifier,UMI)对残留噪 ...

  10. iOS 网易彩票-6设置模块三(常用小功能)

    该篇文章中,用到很多iOS开发过程中常用的小功能,当前只是将这些功能集成到网易彩票的设置中.iOS-常用小功能介绍,请参考我的另一篇文章: iOS 常用小功能 总结:http://www.cnblog ...