据说挪动端 click 有个延时 300ms 响应的机制,目标是为了辨别单击、双击。如果 300ms 内再次点击,则断定为双击,挪动端的双击用于缩放页面;否则为单击,执行 click 的事件处理函数。
勾销 click 延时响应的两种做法:
- 设置视口标签,禁用缩放页面性能,浏览器也会相应勾销对双击的响应。
- 利用 touch 系列事件包装一组监听器,只有 touch 持续时间小于某个值才归为点击(大于就是长按或者拖拽了),进而执行事件处理函数。
按理说,当初挪动端都会设置 viewport:
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, min-scale=1.0, max-scale=1.0">
所以,第 2 种做法有点脱裤子放屁的感觉?
好奇到底提早多久,真的 300ms?于是写了第 2 种做法的监听函数 setFastClick,并检测了理论延时,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, min-scale=1.0, max-scale=1.0"> -->
<!-- <meta name="viewport" content="width=device-width"> -->
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 200px;
height: 200px;
background-color: pink;
}
p {
width: 200px;
height: 200px;
background-color: green;
}
</style>
</head>
<body>
<div>click me and console.log('fast click')</div>
<p>click me and console.log('normal, slow and delay click')</p>
<script>
function setFastClick(obj, callback) {
var isMove = false;
var startTime = 0;
obj.addEventListener('touchstart', function () {startTime = Date.now();
});
obj.addEventListener('touchmove', function () {isMove = true;});
obj.addEventListener('touchend', function () {
// 触摸开始至完结小于 150ms 算点击;高于 150ms、滑动等等可能归为长按、拖动
if (isMove == false && Date.now() - startTime < 150) {callback && callback();
}
isMove = false;
startTime = 0;
});
}
var div = document.querySelector('div');
var divStart = 0;
div.addEventListener('touchstart', function () {divStart = Date.now();
});
setFastClick(div, function () {console.log('fast click, react time:' + (Date.now() - divStart));
divStart = 0;
});
var p = document.querySelector('p');
var pStart = 0;
p.addEventListener('touchstart', function () {pStart = Date.now();
});
p.addEventListener('click', function () {console.log('normal, slow and delay click, react time:' + (Date.now() - pStart));
pStart = 0;
});
</script>
</body>
</html>
设置视口标签禁用缩放后,浏览器就间接勾销 click 延时机制了。所以,这里要把 viewport 正文掉。
然而,一开始我认为删掉 initial-scale=1.0 就行了,后果愣是没呈现延时,响应工夫都是几十毫秒。起初一狠心把 viewport 整行去掉,才发现了的确延时了 300ms。
想想也是,width=device-width 意思就是页面宽度等于设施宽度,就是通知浏览器不用缩放了,浏览器也就勾销 click 延时了。