移动页面click延迟引发的touch问题
一、事件捕获与冒泡
先扯一下事件的触发流程,这个之后会用到。
DOM2级事件规定事件包括三个阶段:
① 事件捕获阶段
② 处于目标阶段
③ 事件冒泡阶段
大概的流程就是事件从最外层一层一层往里面传递(捕获阶段), 到达触发事件的目标元素(目标阶段),然后再一层一层往上冒泡(冒泡阶段)。这个流程事件所经过的元素绑定的对应事件的侦听器都会被触发。例如对元素p的子元素c绑定点击事件,点击元素c后会先在p触发点击事件,使用dispatch触发也是。
PS:事件侦听通过target.addEventListener(type, listener[, useCapture])添加,useCapture参数代表是否在捕获阶段触发事件。
二、click事件的300ms延迟
移动设备中使用click事件和在PC端会有所不同,大多数基于触摸的浏览器设备,在点击时都会有个300ms的事件触发等待时间,原因在于单击后面还有个双击缩放动作,这个涉及到触摸设备的手势交互行为原生设计,设备需要通过时间判断是单击还是双击。
对于这300ms的延迟,根据网上搜索的资料,可通过几个简单的方法解决:
- 无视之。。。如果所涉及业务对点击的反应时间要求不大,300ms其实是可以忽略的。
- 在 chrome 和 firefox 的移动版本中,禁用页面缩放可消除该延迟。不过只兼容这两种不好。
- 在 chrome 32+ 中,设置 viewport 的宽度小于或等于物理设备的宽度。因为只支持chrome 32+,所以也忽略。
- IE10+中设置CSS触摸 action 属性。以后其他浏览器可能也会支持。但目前只支持IE10+,所以也忽略。
- 使用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问题的更多相关文章
- JS click延迟解决方案
click延迟解决方案 移动端click事件会有300ms的延迟,原因是移动端屏幕双击会缩放页面 1.禁止缩放功能 浏览器禁用默认双击缩放行为去掉300ms的点击延迟 user-scalabl ...
- 聊聊click延迟和点击穿透
博客原文地址:Claiyre的个人博客 https://claiyre.github.io/ 如需转载,请在文章开头注明原文地址 移动端click事件被延迟 移动端的开发经常需要监听用户的双击行为,所 ...
- zepto的touch模块解决click延迟300ms问题以及点透问题的详解
大家都知道移动端的click事件会延迟300ms触发,这时大家可以使用zepto的touch模块,里面定义了一个tap事件,通过绑定tap事件,可以实现点击立即触发的功能. 那么,它的tap事件是怎么 ...
- 移动端click延迟和tap事件
一.click等事件在移动端的延迟 click事件在移动端和pc端均可以触发,但是在移动端有延迟现象. 1.背景 由于早期移动设备浏览网页时内容较小,为了增强用户体验,苹果公司专门为移动设备设计了双击 ...
- AlloyTouch Button插件-不再愁click延迟和点击态
移动端不能使用click,因为click会有300ms.所有有了fastclick这样的解决方案.然后fastclick并没有解决点击态(用户点击的瞬间要有及时的外观变化反馈)的问题.hover会有不 ...
- 开发移动端web页面click事件失效问题
这两天在做一个WAP页面,在chrome上模拟移动端的时候,都好好的,然而放到手机上测试时, 发现有些点击事件直接无反应,但是有些有反应: 难道是由于我页面上有用到滚动插件,里面的touch事件的pr ...
- 由单页面web应用引发的企业应用问题
由于单页面web应用的流行,client与server端之间都对应的产生了一些微妙的变化,比方,client原来仅仅是用来展示页面和理清逻辑,而现在逐渐转变成了一个可以进入驱动状态的应用程序. 未来的 ...
- javascript js 完美解决 click 与 dblclick 冲突,并且不会导致click延迟
示例代码: marker.addEventListener("click", function(){ if (!window.markerClicked) { window.mar ...
- bug:页面交互操作引发的问题
最近在测试一些h5页面,突然悟到一些测试点 需求点: 用户可以在页面领取礼物,领取的礼物在页面底部展示,用户点击礼物可调起分享弹窗,礼物超过一屏可左右滑动, bug的表现形式: 仅当礼物超过一屏时(一 ...
随机推荐
- lamp docker apache2 supervisor monitor
sudo docker run -d -p 80:80 -p 3306:3306 -v /data/lampp/supervisormonitor:/app --name mylamp01 tutum ...
- 【python基础】字符串格式化(% VS format)
字符串格式化 Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存. 1.百分号方式 ...
- Mirror--如何对运行中的镜像端点更换证书
如果使用证书配置镜像时,没有设置证书的时间,则默认证书有效期为一年,当证书快过期时,需要更换证书. 下面代码演示如何对正在运行的镜像更换证书 --=========================== ...
- linux基础(1)-终端&shell类型&命令&文件系统&命令帮助的获取
终端 用于与主机交互,必然用到的设备. 物理终端 直接接入本机的显示器和键盘设备:Console. 虚拟终端 附加在物理终端之上的以软件方式虚拟实现的终端,CentOS 6 默认启动 6 个虚拟终端. ...
- [dt]世纪历史长河年代表
年代口诀 夏商与西周, 东周分两段, 春秋和战国, 一统秦两汉, 三分魏蜀吴, 二晋前后延, 南北朝并列, 隋唐五代传, 宋元明清后, 皇朝至此完. 中国历史长河年代表 参考: 中国历史朝代顺序表.年 ...
- jenkins 项目发布脚本
构建shell #!/bin/bash ########################################################################## 编译部分 ...
- python3中pymysql模块安装及连接数据库(同‘python安装HTMLTestRunner’)
https://pypi.org/project/PyMySQL/#files 安装完成之后就是连接数据库了 机器上安装了mysql的数据库,并且已经创建了两张表用于测试 python3连接数据库及删 ...
- Ubuntu 14.04 安装 SteamOS 会话
如何在Ubuntu 14.04上安装steamos会话,以使用户的SteamOS 大图片模式直接从lightdm GTK迎宾开始进入. SteamOS是一个开源的基于Debian Wheezy分支的. ...
- Summary: Java中函数参数的传递
函数调用参数传递类型(java)的用法介绍. java方法中传值和传引用的问题是个基本问题,但是也有很多人一时弄不清. (一)基本数据类型:传值,方法不会改变实参的值. public class Te ...
- c#中WMI 中的日期和时间转为本地时间
取得的值:CreationDate:20170122084915 .713600+480 转: var objQuery = new ObjectQuery("select * from ...