移动端延迟300ms的原因以及解决方案
一、前言
移动端浏览器提供一个特殊的功能:双击(double tap)缩放。
二、移动端延迟300ms的原因
为什么要用触摸事件?触摸事件是移动端浏览器特有的html5事件。
因为移动端的click有很大延迟(大约300ms),300ms延迟来自判断双击和长按,因为只有默认等待时间结束以确定没有后续动作发生时,才会触发click事件。而触摸事件的延迟则是非常短的,使用触摸事件的能够提高页面响应速度,带来更好的用户体验。
重点:由于移动端会有双击缩放的这个操作,因此浏览器在click之后要等待300ms,看用户有没有下一次点击,也就是这次操作是不是双击。
三、浏览器开发商的解决方案
1、方案一:禁用缩放
当HTML文档头部包含如下meta
标签时:
<meta name="viewport" content="user-scalable=no">
<meta name="viewport" content="initial-scale=1,maximum-scale=1">
表明这个页面是不可缩放的,那双击缩放的功能就没有意义了,此时浏览器可以禁用默认的双击缩放行为并且去掉300ms的点击延迟。
缺点:就是必须通过完全禁用缩放来达到去掉点击延迟的目的,然而完全禁用缩放并不是我们的初衷,我们只是想禁掉默认的双击缩放行为,这样就不用等待300ms来判断当前操作是否是双击。但是通常情况下,我们还是希望页面能通过双指缩放来进行缩放操作,比如放大一张图片,放大一段很小的文字。
2、方案二:更改默认的视口窗口
为了让桌面站点能在移动端浏览器正常显示,移动端浏览器默认的视口宽度!=设备浏览器视窗宽度,而是视口宽度要比设备宽度大,通常是980px。
我们可以通过以下标签来设置视口宽度为设备宽度。
<meta name="viewport" content="width=device-width">
对移动端坐过适配和优化了,这个时候就不需要双击缩放了。如果能够识别出一个网站是响应式的网站,那么移动端浏览器就可以自动禁掉默认的双击缩放行为并且去掉300ms的点击延迟。如果设置了上述meta
标签,那浏览器就可以认为该网站已经对移动端做过了适配和优化,就无需双击缩放操作了。
这个方案相比方案一的好处在于,它没有完全禁用缩放,而只是禁用了浏览器默认的双击缩放行为,但用户仍然可以通过双指缩放操作来缩放页面。
除了IE之外的大部分浏览器都不支持这个新的CSS属性。touch-action这个CSS属性。这个属性指定了相应元素上能够触发的用户代理(也就是浏览器)的默认行为。如果将该属性值设置为touch-action: none,那么表示在该元素上的操作不会触发用户代理的任何默认行为,就无需进行300ms的延迟判断。
四、代码解决方案
1、方案一:指针事件polyfill
除了IE,其他大部分浏览器都还不支持指针事件。有一些JS库,可以让我们提前使用指针事件。比如:
(1)谷歌的Polymer
(2)微软的HandJS
(3)@Rich-Harris 的 Points
关心的不是指针事件,而是与300ms延迟相关的CSS属性touch-action。由于除了IE之外的大部分浏览器都不支持这个新的CSS属性,所以这些指针事件的polyfill必须通过某种方式去模拟支持这个属性。一种方案是JS去请求解析所有的样式表,另一种方案是将
touch-action
作为html标签的属性。
2、方案二:FastClick
FastClick是FT Labs专门为解决移动端浏览器 300 毫秒点击延迟问题所开发的一个轻量级的库。FastClick的实现原理是在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后的click事件阻止掉。
五、点击穿透问题
说完移动端点击300ms延迟的问题,还不得不提一下移动端点击穿透的问题。既然click点击有300ms的延迟,那对于触摸屏,我们直接监听touchstart事件不就好了吗?
使用touchstart去代替click事件有两个不好的地方。
第一:touchstart是手指触摸屏幕就触发,有时候用户只是想滑动屏幕,却触发了touchstart事件,这不是我们想要的结果;
第二:使用touchstart事件在某些场景下可能会出现点击穿透的现象。
1、什么是点击穿透?
假如页面上有两个元素A和B。B元素在A元素之上。我们在B元素的touchstart事件上注册了一个回调函数,该回调函数的作用是隐藏B元素。我们发现,当我们点击B元素,B元素被隐藏了,随后,A元素触发了click事件。
这是因为在移动端浏览器,事件执行的顺序是touchstart > touchend > click。而click事件有300ms的延迟,当touchstart事件把B元素隐藏之后,隔了300ms,浏览器触发了click事件,但是此时B元素不见了,所以该事件被派发到了A元素身上。如果A元素是一个链接,那此时页面就会意外地跳转。
2、点击穿透现象3种情况
(1)点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件。
(2)跨页面点击穿透问题:如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转因为 a标签跳转默认是click事件触发 ,所以原理和上面的完全相同
(3)点击穿透问题:这次没有mask了,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了。
3、解决方案
2种思路:
(1)不要混用touch和click。既然touch之后300ms会触发click,只用touch或者只用click就自然不会存在问题了。
(2)用掉(或者说是消费掉)touch之后的click。依旧用tap,只是在可能发生点击穿透的情形做额外的处理,拿个东西来挡住、或者tap后延迟350毫秒再隐藏mask、pointer-events、在下面元素的事件处理器里做检测(配合全局flag)
详细方案:
(1)只用touch
最简单的解决方案,完美解决点击穿透问题。
把页面内所有click全部换成touch事件 touchstart
、’touchend’、’tap’, 需要特别注意 a标签,a标签的href也是click,需要去掉换成js控制的跳转,或者直接改成span + tap控制跳转。
(2)只用click
下下策 ,因为会带来300ms延迟,页面内任何一个自定义交互都将增加300毫秒延迟,想想都慢。不用touch就不会存在touch之后300ms触发click的问题。
(3)拿个东西挡住
比较笨的方法, 千万不要用。更多信息请查看 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)
(4)tap后延迟350ms再隐藏mask
改动最小,缺点是隐藏mask变慢了,350ms还是能感觉到慢的。
(5)pointer-events
比较麻烦且有缺陷, 不建议使用。mask隐藏后,给按钮下面元素添上 pointer-events: none; 样式,让click穿过去,350ms后去掉这个样式,恢复响应。缺陷是mask消失后的的350ms内,用户可以看到按钮下面的元素点着没反应,如果用户手速很快的话一定会发现。
(6)在下面元素的事件处理器里做检测(配合全局flag)
比较麻烦, 不建议使用。全局flag记录按钮点击的位置(坐标点),在下面元素的事件处理器里判断event的坐标点,如果相同则是那个可恶的click,拒绝响应。
(7)fastclick
好用的解决方案,不介意多加载几KB的话, 不建议使用 ,因为有人遇到了bug,更多信息请查看: Fastclick 导致click事件触发两次的问题。
首先引入fastclick库,再把页面内所有touch事件都换成click,其实稍微有点麻烦,建议引入这几KB就为了解决点透问题不值得,不如用第一种方法呢。
六、浏览器事件触发的顺序
touchstart --> mouseover(有的浏览器没有实现) --> mousemove(一次) -->mousedown --> mouseup --> click -->touchend
Touch 事件中,常用的为 touchstart, touchmove, touchend 三种。除此之外还有touchcancel。 注意,原生事件中并没有tap事件。
事件描述如下:
事件 | 描述 | 触发时机 |
---|---|---|
touchstart | 开始触摸 | 手指接触屏幕时立即触发 |
touchmove | 移动或拖拽 | 取决于系统和浏览器 |
touchend | 触摸结束 | 手指离开屏幕时立即出发 |
而Touch事件的触发一般通过手指,还会存在多点触控,拖拽方向等情况。列出几个重要参数如下:
参数 | 含义 |
---|---|
touches | 屏幕中每根手指信息列表 |
targetTouches | 和touches类似,把同一节点的手指信息过滤掉 |
changedTouches | 响应当前事件的每根手指的信息列表 |
代码获取如下:
elemenrRef.addEventListener('touchstart', function(e) {
console.log(e.touches, e.targetTouches, e.changedTouches);}
);
手指触发触摸事件的过程如下:
touchstart --> mouseover(有的浏览器没有实现) --> mousemove(一次) -->mousedown --> mouseup --> click -->touchend
由此,我们可以在 ontouchstart 事件上记录开始触摸开始,ontouchend 记录触摸结束信息。 通过上述这些参数,很容易的去计算幽冥点击的时间,以及点击穿透的相关信息,包括响应的坐标情况。
如若转载,请注明出处:sau交流学习社区-power by saucxs(程新松)(/page/626.html)
- 记录一次nginx故障:recv() failed (104: Connection reset by peer) while reading response header from upstream,
- 微信小程序初体验,入门练手项目--通讯录,部署上线(二)
- 微信小程序初体验,入门练手项目--通讯录,后台是阿里云服务器(一)
- thinkjs性能优化之nginx配置
- 开学AI登场!南京高校用人脸识别查考勤管理学生,还敢逃课、玩手机?姚AI变脸热到爆!开源换脸工具FakeSwap今登GitHub排行榜第二位,ICLR飞升,IJCAI降级:清华的新版AI顶会评级引发学术圈热议,意外!已获6700万美元投资的自动驾驶LiDAR创业公司关门了
标签云
图文推荐
“深度学习”这十年:52篇大神级论文再现AI荣与光,12岁上大学、31岁成最年轻IEEE Fellow,前百度总裁张亚勤加盟清华,全球女性福音!DeepHealth深度学习模型检测乳腺癌完胜5名放射科医师,读博无门,就业碰壁,孤独当了7个月“民科”后,我的论文中了顶会Spotlight
saucxs 2020-01-03 10:04:09
1200 万部手机、500 亿实时位置数据,上帝视角还原特朗普全天行踪,自动驾驶玩漂移 斯坦福最新研究:《头文字D》无人车版来了,印度裔又要统领美国科学界?特朗普提名他领导美国国家科学基金会,GitHub排名第一!免费最强“抢票神器”在手,程序员抢票再不用跪求加速包
saucxs 2019-12-25 10:08:05
蝉联AI专业全球冠军!清华力压CMU再夺CSRankings高校AI排行王座,波士顿动力CEO:不排斥军方订单,就想你粗暴地对待机器狗,亚马逊Alexa突然发疯,读着论文教主人自杀:你活着地球人口会过剩,图神经网络的ImageNet?斯坦福大学等开源百万量级OGB基准测试数据集
saucxs 2019-12-24 09:57:45
2020 AAAI Fellow名单出炉!深度学习先驱Bengio和LeCun双双入选,李世石最后一战不敌AI“韩豆”!唯一战胜过AlphaGo的男人正式退役,GAN和PS合体会怎样?东京大学图像增强新研究:无需配对图像,增强效果还可解释,2019年最受关注的100项研究,AI“复活”蒙娜丽莎排第一
saucxs 2019-12-23 09:58:10
这家AI公司用面具破解中国人脸识别系统!微信、支付宝、火车站无一幸免,OpenAI公开Dota 2论文:胜率99.4%,「手术」工具连续迁移训练,9岁神童大学毕业前突然退学,转赴美国攻读电气工程博士,Reddit热议:15岁高中生用神经网络建立生命进化“新宇宙”
saucxs 2019-12-17 09:45:30
- 东方财富
- saucxs博客园
- weekly周报
- loveBook
- 前端博客
- 技术交流学习社区
- saucxs
- segmentfault
- saucxs的博客
- haorooms
- luckyscript
- 东方财富期货
- 峰云就她了
- binlive
- songEagle
- 且听风吟
- (TX)Heying Ye
- CG Online Judge
- Chris's Blog
- vueRouter
- 龙恩0707
- 鑫空间,鑫生活
- 木易杨
- MDN-js
- Cherry's Blog
- InterviewMap
- 安安哥的小戏台
- xiaojun1994-cat
- JavaScript-Garden
- junruchen-daily
- 秋天爱美丽
- web-summary-daily
- w3cplus-tb
- 潜行者m
- 于江水
- KieSun-git
- cnodejs
- aerminBlog
- fex_bd
- gwuhaolin-git
- Deboy's Blog
- react-china
- react.docschina
- Vuejs社区
- vuejsDoc
- cdnSocketIo
- shuaihuaCC
- colorize
- stazhu
- 前端学习
- IBM Dev社区
- linux运维笔记
- webpackDoc
- sayskyGithub
- 前端里
- 996.ICU
- electronjs
- CS-Notes
- mqyqingfengBlog
- beego官方
- 编码规范
- 阮一峰个人网站
- sessionstack
- damonareGoUp
- 咀嚼之味
- fe-interview
- xd-tayde/blog
- css-tricks
- ghmagical个人中心
- markyunp6
- hellogithub
- 霜序廿
- rin部落
- 建站素材
- 前端资源网
- CSS开发手册
- web技术交流
- 程新松个人网站
- wangEditor
- 小松博客
- 交流学习社区