一、事件捕获与冒泡

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

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. web window pixel等笔记

    原文:http://www.w3cplus.com/css/viewports.html 屏幕尺寸 Screen size =显示器尺寸 screen.width 和 screen.height.这两 ...

  2. HandlerSocket

    HandlerSocket http://www.uml.org.cn/sjjm/201211093.asp 目录: HandlerSocket的原理 HandlerSocket的优势和缺陷阐述 Ha ...

  3. Javaweb开发请求

    1.Ajax jQuery对Ajax支持:$.ajax({  }); ==>常用参数:url:请求地址,type:post|get,data:请求参数,dataType:服务器返回数据类型,su ...

  4. 关于Flag的定义

    最近在维护项目的代码,发现了由于Flag不一致导致的很多问题,现在对这一问题总结. 1,flag分为两种,可以组合的和不可以组合的.可以组合的flag适合用每一位表示一个含义.不适合组合的flag适合 ...

  5. 安恒X计划12月月赛

    ezweb 主要是序列化问题.没有PHP环境,在线运行的.实例化对象之后修改一下file.然后echo输出序列化的结果.不过下面有一个正则检查.数字前加一个+,影响了正则的匹配,但是对于序列化的还原没 ...

  6. numpy的prod()函数和pad()函数

    1.np.prod()函数用来计算所有元素的乘积,对于有多个维度的数组可以指定轴,如axis=1指定计算每一行的乘积. 2.np.lib.pad()函数用来把原来的list在原来的维度上进行扩展 例1 ...

  7. LeetCode Python 位操作 1

    Python 位操作: 按位与 &, 按位或 | 体会不到 按位异或 ^ num ^ num = 0 左移 << num << 1 == num * 2**1 右移 & ...

  8. Selenium - Xpath 使用方法

    由于最新版火狐不在支持FireBug等开发工具,可以通过https://ftp.mozilla.org/pub/firefox/releases/下载49版本以下的火狐就可以增加Firebug等扩展了 ...

  9. Ember.js学习教程 -- 目录

    写在前面的话: 公司的新项目需要用到Ember.js,版本为v1.13.0.由于网上关于Ember的资料非常少,所以只有硬着头皮看官网的Guides,为了加深印象和方便以后查阅就用自己拙劣的英语水平把 ...

  10. SQL 中单引号 和一些特殊字符的处理

    为了防止程序SQL语句错误以及SQL注入,单引号必须经过处理.有2种办法: 1.使用参数,比如SELECT * FROM yourTable WHERE name = @name; 在Java中就是用 ...