1、概况
说完移动端点击300ms延迟的问题,还不得不提一下移动端点击穿透的问题。可能有人会想,既然cick点击有300ms的延迟,那对于触摸屏,我们直接监听 touchstart事件不就好了吗?
使用 touchstart去代替click事件有两个不好的地方。
- 1、touchstart昰指触摸屏幕就触发,有时候用户只是想滑动屏幕,却触发了 touchstart事件,这不是我们想要的结果。
- 2、使用 touchstart事件在某些场景下可能会出现点击穿透的现象。
什么是点击穿透?
假如页面上有两个元素A和B,B元素在A元素之上,B为遮罩层mask。我们在B元素上绑定 touchstart事件,作用是隐藏B元素;A元素上绑定click事件。我们发现,当我们点击B元素,B元素被隐藏了,随后,也触发了A元素的click事件。
点击穿透的原因
这是因为在移动端浏览器,事件执行的顺序是 touchstart ==>touchmove==>touched ==>click
。而click事件有300ms的延迟,当 touchstart事件把B元素隐藏之后,隔了300ms,浏览器触发了click事件,但是此时B元素不见了,所以该事件被派发到了A元素身上。如果A元素是一个链接,那此时页面就会意外地跳转了。
2、解决点击穿透问题的办法
办法一:延迟上层元素的消失
touchstart后延迟350ms再隐藏mask。先把透明度设置为0,解决视觉层面的效果,在设置定时器延迟,让A元素消失。
$('.mask').on('touchstart',function() {
console.log('mask-touchstart');
$(this).css('opacity', 0);
setTimeout(function() {
$('.mask').css('dispaly', 'none');
},350);
})
办法二:pointer-events,让被覆盖元素短时间内无法触发click
有必要介绍一个 CSS3 的属性 —— pointer-events。
pointer-events 属性
- auto:默认值,鼠标或触屏事件不会穿透当前层
- none:使元素无法触发事件
$('.mask').on('touchstart',function() {
console.log('mask-touchstart');
$(this).css('display', 'none');
//让被覆盖元素无法响应click
$('.box').css('pointer-events', 'none');
//恢复被覆盖元素
setTimeout(function() {
$('.box').css('pointer-events', 'auto');
},300);
})
办法三:使用fastclick库
使用fastclick库,从此所有的点击事件都使用click,没有300ms的延迟,也没有穿透问题
//1、引入fastclick
<script src="js/fastclick.min.js"></script>
//2、原生js初始化
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
//3、直接像往常一样,调用即可
var div = document.querySelector('div');
div.addEventListener('click',function(){
alert(111);
})
办法四:针对安卓的,android:clickable="true"
在上层的布局中增加android:clickable="true"的属性,这样下层的事件就不会被触发了。
参考链接:https://www.cnblogs.com/leftJS/p/11095226.html