fastclick 解决移动端点击事件延迟300ms和点击穿透的问题

延迟

为什么移动端点击事件会有300ms延迟?

首款 iPhone开发时遇到一个问题:当时的网站都是为大屏幕设备所设计的,而小屏幕浏览桌面端站点的缩放时如何系统判断?于是做出一个双击缩放(double tap to zoom)的约定,这也是会有上述 300 毫秒延迟的主要原因。
双击缩放,顾名思义,即用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页缩放至原始比例。 那么这和 300 毫秒延迟有什么联系呢?
假定这么一个场景: 用户在 iOS Safari 里边点击了一个链接。由于用户可以进行双击缩放或者双击滚动的操作,当用户一次点击屏幕之后,浏览器并不能立刻判断用户是确实要打开这个链接,还是想要进行双击操作。因此,iOS Safari 就等待 300 毫秒,以判断用户是否再次点击了屏幕。 鉴于iPhone的成功,其他移动浏览器都复制了 iPhone Safari 浏览器的多数约定,包括双击缩放,几乎现在所有的移动端浏览器都有这个功能。

解决办法

  1. 禁用缩放

    <meta name = "viewport" content="user-scalable=no" > 
    

    缺点: 网页无法缩放

  2. 更改默认视口宽度

    <meta name="viewport" content="width=device-width">
    
  3. css touch-action

    touch-action:auto; //将其置为 none 即可移除目标元素的 300 毫秒延迟
    
  4. 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'),()=>{
     	//执行代码 
    })
    
  5. 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

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值