延迟
为什么移动端点击事件会有300ms延迟?
首款 iPhone开发时遇到一个问题:当时的网站都是为大屏幕设备所设计的,而小屏幕浏览桌面端站点的缩放时如何系统判断?于是做出一个双击缩放(double tap to zoom)的约定,这也是会有上述 300 毫秒延迟的主要原因。
双击缩放,顾名思义,即用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页缩放至原始比例。 那么这和 300 毫秒延迟有什么联系呢?
假定这么一个场景: 用户在 iOS Safari 里边点击了一个链接。由于用户可以进行双击缩放或者双击滚动的操作,当用户一次点击屏幕之后,浏览器并不能立刻判断用户是确实要打开这个链接,还是想要进行双击操作。因此,iOS Safari 就等待 300 毫秒,以判断用户是否再次点击了屏幕。 鉴于iPhone的成功,其他移动浏览器都复制了 iPhone Safari 浏览器的多数约定,包括双击缩放,几乎现在所有的移动端浏览器都有这个功能。
解决办法
-
禁用缩放
<meta name = "viewport" content="user-scalable=no" >
缺点: 网页无法缩放
-
更改默认视口宽度
<meta name="viewport" content="width=device-width">
-
css touch-action
touch-action:auto; //将其置为 none 即可移除目标元素的 300 毫秒延迟
-
tap事件
zepto的tap事件, 利用touchstart和touchend来模拟click事件//封装tap解决click 300ms 延时 function tap (obj,callback) { var isMove = false;//记录手指是否移动 var startTime = 0;//记录手指触摸的时间 obj.addEventListener('touchstart',function(e){ startTime = Date.now();//记录触摸时间 }) obj.addEventListener('touchmove',function(e){ isMove = true;//查看手指是否滑动 }) obj.addEventListener('touchend',function(e){ if(!isMove && (Date.now() - statrTime) < 150){ callback && callback(); } isMove = false;//取反 重置 startTime = 0; }) }; tap(document.getElementById('dom'),()=>{ //执行代码 })
-
fastclick
在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后真正的click事件阻止掉<script type='application/javascript' src='./fastclick.js'></script> if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); }
<script type='application/javascript' src='./jquery.js'></script> <script type='application/javascript' src='./fastclick.js'></script> $(function() { FastClick.attach(document.body); });
var attachFastClick = require('fastclick'); attachFastClick(document.body);
缺点: 脚本相对较大
点透
为什么移动端点击事件会有点击穿透?
这是因为在移动端浏览器,事件执行的顺序是touchstart > touchend > click
。而click事件有300ms的延迟,当touchstart事件把B元素隐藏之后,隔了300ms,浏览器触发了click事件,但是此时B元素不见了,所以该事件被派发到了A元素身上。
<style>
.box{width: 500px;height: 500px;border: 1px solid #ccc;position: relative;}
.click{width: 300px;height: 300px;background-color: blue;}
.tap{width: 200px;height: 200px;background-color: red;position: absolute;left: 0;top:0;}
</style>
<body>
<div class="box">
<div class="click"></div>
<div class="tap"></div>
</div>
</body>
<script>
var click = document.querySelector(".click");
var tap = document.querySelector(".tap");
tap.addEventListener("touchstart",function(){
tap.style.visibility = "hidden";
console.log(123);
})
click.addEventListener("click",function(){
console.log(456);
})
</script>
点击 tap
打印 123 456
,tap标签隐藏
<script src="./fastclick.js"></script>
<script>
FastClick.attach(document.body);
var click = document.querySelector(".click");
var tap = document.querySelector(".tap");
tap.addEventListener("touchstart",function(){
tap.style.visibility = "hidden";
console.log(123);
})
click.addEventListener("click",function(){
console.log(456);
})
</script>
点击 tap
打印 123
,tap标签隐藏
点击 click
打印 456