移动端300ms延迟由来及解决方案
1、300ms延迟由来
300 毫秒延迟的主要原因是解决双击缩放(double tap to zoom)。双击缩放,顾名思义,即用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页缩放至原始比例。 那么这和 300 毫秒延迟有什么联系呢? 假定这么一个场景。用户在 iOS Safari 里边点击了一个链接。由于用户可以进行双击缩放或者双击滚动的操作,当用户一次点击屏幕之后,浏览器并不能立刻判断用户是确实要打开这个链接,还是想要进行双击操作。因此,iOS Safari 就等待 300 毫秒,以判断用户是否再次点击了屏幕。 鉴于iPhone的成功,其他移动浏览器都复制了 iPhone Safari 浏览器的多数约定,包括双击缩放,几乎现在所有的移动端浏览器都有这个功能。、
2、解决方案
(1)添加viewpoint meta标签
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
(2)FastClick
https://github.com/ftlabs/fastclick
移动端事件触发顺序:在移动端,手指点击一个元素,会经过:touchstart --> touchmove -> touchend -->click。
fastclick.js的原理是:FastClick的实现原理是在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后真正的click事件阻止掉。
fastclick同样可以解决移动端点透现象。
点透现象:当A/B两个层上下z轴重叠,上层的A点击后消失或移开(这一点很重要),并且B元素本身有默认click事件(如a标签)或绑定了click事件。在这种情况下,点击A/B重叠的部分,就会出现点透的现象。点透现象的关键点:
A/B两个层上下z轴重叠。
上层的A点击后消失或移开。(这一点很重要)
B元素本身有默认click事件(如a标签) 或 B绑定了click事件。
在以上情况下,点击A/B重叠的部分,就会出现点透的现象。
示例代码:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>移动端点透现象</title> <style> * { margin: 0px; padding: 0px; } #div1 { /*红色半透明遮盖层A*/ width: 300px; height: 300px; background-color: rgba(255, 0, 0, 0.25); } #div2 { /*黄色内容层B*/ width: 240px; height: 240px; background-color: yellow; position: absolute; left: 30px; top: 30px; z-index: -1; } #console { /*绿色状态输出框*/ border: 1px solid green; position: absolute; top: 300px; width: 100%; } </style> </head> <body> <div id="div1"></div> <div id="div2"> <a href="https://www.baidu.com/">www.baidu.com</a> </div> <div id="console"></div> <script type="text/javascript"> var div1 = document.getElementById("div1"); var div2 = document.getElementById('div2'); function handle(e) { var tar = e.target, eve = e.type; console.log("target:" + tar.id + " event:" + eve) if(tar.id === "div1") { div1.style.display = "none"; } } div1.addEventListener("touchend", handle); div1.addEventListener("touchstart", handle); div2.addEventListener('click', handle); </script> </body> </html>
解决方法:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <title>移动端点透现象解决方法</title> <style> * { margin: 0px; padding: 0px; } #div1 { /*红色半透明遮盖层A*/ width: 300px; height: 300px; background-color: rgba(255, 0, 0, 0.25); } #div2 { /*黄色内容层B*/ width: 240px; height: 240px; background-color: yellow; position: absolute; left: 30px; top: 30px; z-index: -1; } #console { /*绿色状态输出框*/ border: 1px solid green; position: absolute; top: 300px; width: 100%; } </style> </head> <body> <div id="div1"></div> <div id="div2"> <a href="https://www.baidu.com/">www.baidu.com</a> </div> <div id="console"></div> <script src="https://cdn.bootcss.com/fastclick/1.0.6/fastclick.min.js"></script> <script type="text/javascript"> if('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); } var div1 = document.getElementById("div1"); var div2 = document.getElementById('div2'); function handle(e) { var tar = e.target, eve = e.type; console.log("target:" + tar.id + " event:" + eve) if(tar.id === "div1") { div1.style.display = "none"; } } div1.addEventListener("touchend", handle); div1.addEventListener("touchstart", handle); div2.addEventListener('click', handle); </script> </body> </html>