移动端为何不使用click而模拟tap事件及解决方案
移动端click会遇到2个问题,click会有200-300ms的延迟,同时click事件的延迟响应,会出现穿透,即点击会触发非当前层的点击事件。
为什么会存在延迟?
Google开发者文档中有提到:
mobile browsers will wait approximately 300ms from the time that you tap the button to fire the click event. The reason for this is that the browser is waiting to see if you are actually performing a double tap.
移动浏览器为什么会设置300毫秒的等待时间呢?这与双击缩放的方案有关。平时我们有可能已经注意到了,双击缩放,即用手指在屏幕上快速点击两次,可以看到内容或者图片放大,再次双击,浏览器会将网页缩放至原始比例。
浏览器捕获第一次单击后,会先等待一段时间,如果在这段时间区间里用户未进行下一次点击,则浏览器会做单击事件的处理。如果这段时间里用户进行了第二次单击操作,则浏览器会做双击事件处理。这段时间就是上面提到的300毫秒延迟。
touch事件的来源
PC网页上的大部分操作都是用鼠标的,即响应的是鼠标事件,包括mousedown、mouseup、mousemove和click事件。一次点击行为,事件的触发过程为:mousedown -> mouseup -> click 三步。
手机上没有鼠标,所以就用触摸事件去实现类似的功能。touch事件包含touchstart、touchmove、touchend,注意手机上并没有tap事件。手指触发触摸事件的过程为:touchstart -> touchmove -> touchend。
手机上没有鼠标,但不代表手机不能响应mouse事件(其实是借助touch去触发mouse事件)。有人在PC和手机上对事件做了对比实验,以说明手机对touch事件相应速度快于mouse事件
点击穿透问题
点击穿透现象主要有3种:
1点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件,蒙层的关闭按钮绑定的是touch事件,而按钮下面元素绑定的是click事件,touch事件触发之后,蒙层消失了,300ms后这个点的click事件fire,event的target自然就是按钮下面的元素,因为按钮跟蒙层一起消失了
2跨页面点击穿透问题:如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转,因为a标签跳转默认是click事件触发,所以原理和上面的完全相同
3另一种跨页面点击穿透问题:这次没有mask了,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了,和蒙层的道理一样,js控制页面跳转的逻辑如果是绑定在touch事件上的,而且新页面中对应位置的元素绑定的是click事件,而且页面在300ms内完成了跳转,三个条件同时满足,就出现这种情况了
4非要细分的话还有第四种,不过概率很低,就是新页面中对应位置元素恰好是a标签,然后就发生连续跳转了。。。诸如此类的,都是点击穿透问题
为什么会出现点透
click延迟,延迟,还是延迟。
在移动端不使用click而用touch事件代替触摸是因为click事件有着明显的延迟,具体touchstart与click的区别如下:
1.touchstart:在这个DOM(或冒泡到这个DOM)上手指触摸开始即能立即触发
2.click:在这个DOM(或冒泡到这个DOM)上手指触摸开始,且手指未曾在屏幕上移动(某些浏览器允许移动一个非常小的位移值),且在这个在这个dom上手指离开屏幕,且触摸和离开屏幕之间的间隔时间较短(某些浏览器不检测间隔时间,也会触发click)才能触发。
也就是说,事件的触发时间按由早到晚排列为:touchstart 早于 touchend 早于 click。亦即click的触发是有延迟的,这个时间大概在300ms左右。
由于我们在touchstart阶段就已经隐藏了罩层A,当click被触发时候,能够被点击的元素则是其下的B元素,根据click事件的触发规则:只有在被触发时,当前有click事件的元素显示,且在面朝用户的最前端时,才触发click事件。
由于B绑定了click事件(或者B本身默认存在click事件),所以B的click事件被触发,产生了点透的情况。
点透的解决方案
1. 使用fastclick库,其实现思路是,取消 click 事件(参看源码 164-173 行),用 touchend 模拟快速点击行为(参看源码 521-610 行)。
FastClick.attach(document.body);
从此所有点击事件都使用click,不会出现“穿透”的问题,并且没有300ms的延迟。
然后给需要“无延迟点击”的元素绑定click事件(注意不再是绑定zepto的tap事件)即可。
也可以不在body上初始化它,而在某个dom上初始化,这样,只有设个dom和它的子元素才能享受"无延迟"的点击
实践开发中,当元素绑定fastclick后,click响应速度比tap还要快一点。
2.为元素绑定touchend事件,并在内部加上e.preventDefault();
$demo.on('touchend',function(e){
//改变了事件名称,tap是body上才被触发,而touchend是原生的事件,在dom本身上就会被捕获触发
$demo.hide();
e.preventDefault();//阻止“默认行为”
});
3 pointer-events
pointer-events是CSS3中的属性,它有很多取值,有用的主要是auto和none,其他属性值为SVG服务。
auto: 效果和没有定义 pointer-events 属性相同,鼠标不会穿透当前层。
none: 元素不再是鼠标事件的目标,鼠标不再监听当前层而去监听下面的层中的元素。但是如果它的子元素设置了pointer-events为其它值,比如auto,鼠标还是会监听这个子元素的。
4只用touch
最简单的解决方案,完美解决点击穿透问题
把页面内所有click全部换成touch事件( touchstart 、’touchend’、’tap’),需要特别注意 a标签,a标签的href也是click,需要去掉换成js控制的跳转,或者直接改成span + tap控制跳转。如果要求不高,不在乎滑走或者滑进来触发事件的话,span + touchend就可以了,毕竟tap需要引入第三方库
不用a标签其实没什么,移动app开发不用考虑SEO,即便用了a标签,一般也会去掉所有默认样式,不如直接用span
tap事件的原理:
tap事件的原理其实是源于触摸touch事件,在移动触摸事件就是在同个点触发,及touchmove的距离距离touchstar的距离为0,并且点击的时间不超过某个设定的时间值,超过该时间值的话,就属于长按了
下面我封装了一个事件,模拟tap事件的原理:
封装tap的方法
function tap(ele,callBack){
//触摸开始的时间
var startTime=0;
//定义touchmove是否触发
var ismove=false;
var maxTime=250;
ele.addEventListener('touchstart',function(e){
startTime=Date.now();
ismove=false;
})
ele.addEventListener('touchmove',function(e){
//触发就赋值为true
ismove=true;
})
ele.addEventListener('touchend',function(e){
//判断是否是touchmove是否触发
if (ismove) {
return;
}
// 判断是否为长按
if ((Date.now()-startTime)>maxTime) {
return;
}
// 如果能够到这里
callBack(e);
})
}
移动端模拟双击事件
var clicked = 1;
var clickedTime={
'timeA':" ",
'timeB':" "
};
var clicking=function()
{
if(clicked==1){
clickedTime.timeA=new Date();
clicked++;
}
else if(clicked==2){
clickedTime.timeB=new Date();
if (Math.abs(clickedTime.timeA-clickedTime.timeB)<400){
// 双击 function
clicked=1;
}else{
clickedTime.timeA=new Date();
};
}
});
移动端 单击事件 与 双击事件 共存 如(单击 则function a() 双击function B())
var clicked = 1;
var clickedTime={
'timeA':" ",
'timeB':" "
};
var clicking=function()
{
if(clicked==1){
// 单击 function
clicked++;
}
else if(clicked==2){
clickedTime.timeA=new Date();
clicked++;
}
else if(clicked==3){
clickedTime.timeB=new Date();
if (Math.abs(clickedTime.timeA-clickedTime.timeB)<400){
// 双击 function
clicked=1;
}else{
clickedTime.timeA=new Date();
};
}
});
移动端为何不使用click而模拟tap事件及解决方案的更多相关文章
- 移动端click延迟和tap事件
一.click等事件在移动端的延迟 click事件在移动端和pc端均可以触发,但是在移动端有延迟现象. 1.背景 由于早期移动设备浏览网页时内容较小,为了增强用户体验,苹果公司专门为移动设备设计了双击 ...
- 模拟tap事件和longTap事件
移动端模拟tap和longTap事件,基本原理就是在touchstart和touchend事件中,计算触摸的位移和时间差,位移在一定范围内(轻微滑动),时间小于150ms为tap事件,时间大于300m ...
- 移动端web开发,click touch tap区别
转自: http://blog.csdn.net/sly94/article/details/51701188 移动端用tap时会有穿透问题 一:click与tap比较 click与tap都会触发点击 ...
- 移动端WEB开发,click,touch,tap事件浅析
一.click 和 tap 比较 两者都会在点击时触发,但是在手机WEB端,click会有 200~300 ms,所以请用tap代替click作为点击事件. singleTap和doubleTap 分 ...
- 移动端click时间、touch事件、tap事件
一.click 和 tap 比较 两者都会在点击时触发,但是在手机WEB端,click会有 200~300 ms,所以请用tap代替click作为点击事件. singleTap和doubleTap 分 ...
- 移动端click时间、touch事件、tap事件详解
一.click 和 tap 比较 两者都会在点击时触发,但是在手机WEB端,click会有 200~300 ms,所以请用tap代替click作为点击事件. singleTap和doubleTap 分 ...
- 浅谈Winform事件的实现以及模拟其事件的实现(附实现源码)
当我们初学Winform的时候被其神奇的事件功能所吸引,当点击一个按钮时,便会跳到我们所写的点击方法当中去.然而这并不符合我们对方法的理解,究竟.net在后面帮助我们实现了什么.我们怎样模拟其事件的实 ...
- js模拟触发事件
html标签元素封装着实用的[事件],但在很多时候,需要[模拟触发事件],比如 [按钮单机事件] 可以实实在在点击按钮触发该事件,但体验而言,很多时候需要js逻辑处理让实现 触发事件的效果这时就用 ...
- JS模拟键盘事件 -- 原理及小例子
提问: 键盘默认事件,比如tab切换,alt+f4关闭,ctrl+t新建等,如果不想通过键盘而是一些按钮点击来触发这些功能,该咋办呢? 例子: 先以tab为例上一个小例子: <!DOCTYPE ...
随机推荐
- ES语法注意事项
在函数内部定义全局变量:举个栗子 function fn(){ var str = "hezhi"; } -alert(str) //=>fn不执行的 =>str is ...
- 我的学习之路_第二十七章_jQuery
jQueryjs类库 把常用对象或者方法封装起来,让我们写代码效率更高 1.jQuery 2.extjs [jQuery入门] jQuery的引入: 通过script标签的src属性引入 入门: 获取 ...
- vijos1698题解
题目: 船体的结构是不能随意修改的..那样会破坏整艘船和谐的韵律.. 虽然说.如果沿岸航行的话是不会预见太大的海浪的..但是还要小心保护轨杆和船帆.. 毕竟对于小s这样的单轨帆船...轨杆和船帆如果受 ...
- React 实践项目 (二)
React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! React 实践项目 (一 ...
- 构建混合应用方式之 - Azure混合连接
前面介绍了通过WCF中继构建混合应用的方式,由于对WCF的依赖,使得其使用有一定的局限性,基本上只适用于本地服务是WCF的.NET应用.而混合连接则弥补了这一块的缺陷,除了支持原有WCF中继的功能之外 ...
- Async(异步)(一)
在谈到异步的概念时,先要了解几个概念了. 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源. 而一个进程又是由多个线程所组成的 什么是线程? 线程 ...
- MAC本上appium连接真机
简单介绍一下appium连接ios真机测试环境的软件安装及配置过程: 目前我用的是desktop版本的appium, 所以MAC版本必须要升级到10.12以上,Xcode版本必须要在8.0以上,否则亲 ...
- vim的tab键设定
多在windows上编程的童鞋可能习惯于感受tab键为4个空格的长度,不过在linux系统中一般默认设定tab键为8个空格长度来显示.事实上tab也确实是8个空格的长度.不过由于习惯问题,某些童鞋还是 ...
- Ambari架构原理
不多说,直接上干货! Ambari 架构原理图 通过三张图来说明: 第一张架构图告诉我们:Ambari是Hortonworks贡献给社区的.完全开源的.Hadoop生态的集群管理.监控.部署的工具: ...
- Java之异常处理,日期处理
Java异常处理 异常:异常就是Java程序在运行过程中出现的错误. 异常由来:问题也是现实生活中一个具体事务,也可以通过java 的类的形式进行描述,并封装成对象.其实就是Java对不正常情况进行描 ...