移动端tap与click的区别 && 点透事件

移动端tap与click的区别 && 点透事件

来源: 博客园 - Wayne-Zhu

1. 移动端的问题

移动端的主要问题是 click 事件会有 300ms的延迟

主要原因是苹果手机在设计时,考虑到用户在浏览网页时需要双击放大,所以,在用户点击的 300ms 之后,才触发 click 事件。如果 300ms 之内还有 click,就会进行放大缩小。

但是,大部分时候放大、缩小是不需要的,开发者也会禁用它们,那么这 300ms 的延迟就是性能上的损耗。

如何解决这300ms的延迟?

在移动端,最容易想到的就是使用 touchend 来替代 click。但是 touchend 是存在很大问题的,因为 touchend 之前可能是 touchstarttouchmove。具体情境可能是:用户滑动页面时,不小心在一个按钮那里触发了 touchend,这样就执行了,但是用户的本意不是如此。

那么该怎么解决呢?

2. tap事件

为了减少这 300ms 的延迟,tap 事件被很多框架(如 Zepto)封装,用来减少延迟问题。tap 事件不是原生的,是封装出来的。

具体是如何实现的呢?主要考虑到下面两点:

  1. 按住的时间不能超过延时时间:因为长时间按住可能就是浏览器的复制、粘贴等操作了。
  2. 不能在页面中移动 :移动是不能触发 tap 事件的。

我们可以自己封装如下:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>tap</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
    <button id="btn">按钮</button>
    <script>
        function tap(ele, callback) {
            // 记录开始时间
            var startTime = 0,
                // 控制允许延迟的时间
                delayTime = 200,
                // 记录是否移动,如果移动,则不触发tap事件
                isMove = false;

            // 在touchstart时记录开始的时间
            ele.addEventListener('touchstart', function (e) {
                startTime = Date.now();
            });

            // 如果touchmove事件被触发,则isMove为true
            ele.addEventListener('touchmove', function (e) {
                isMove = true;
            });

            // 如果touchmove事件触发或者中间时间超过了延迟时间,则返回,否则,调用回调函数。
            ele.addEventListener('touchend', function (e) {
                if (isMove || (Date.now() - startTime > delayTime)) {
                    return;
                } else {
                    callback(e);
                }
            })
        }
        
        var btn = document.getElementById('btn');
        tap(btn, function () {
            alert('taped');
        });
    </script>
</body>
</html>

如上,我们就可以正常使用 tap 事件并且避免了 300ms 延迟的产生。

3. 点透问题 (Ghost Click)

如果我们在移动端所有的 click 都替换为了 tap 事件,还是会触发点透问题

实质是:

在同一个 z 轴上,z-index 不同的两个元素,上面的元素是一个绑定了 tap 事件的,下面是一个 a 标签。一旦 tap 触发,上面的元素就会 display: none(隐藏或消失)。

从上面的 tap 可以看出,有 touchstarttouchend,所以系统会在 300ms 之后触发 click 事件。此时,上层元素的 z-index 已经消失了,所以,触发了下面 a 标签的 click 事件 (注意:认为 a 标签默认是绑定了 click 事件的)。而这种现象不是我们所期待的。

4. 解决方案

解决点透问题通常有以下两种方案:

(1) 使用 fastclick 库

直接引入 fastclick 库,可以有效解决 300ms 延迟和点透问题。

javascript 复制代码
window.addEventListener("load", function () {
    FastClick.attach(document.body);
}, false);

这样就可以成功解决问题了。

(2) 添加一个延迟

对于上一个 tap 事件做延迟处理,等 300ms 之后再隐藏上层元素。

javascript 复制代码
tap(ele, function () {
    setTimeout(function () {
        ele.style.display = 'none';
    }, 300);
})

这样,过了 300ms 后,click 事件就不会触发在下面的 a 标签上了。

相关推荐
雨落在了我的手上1 小时前
Java数据结构(六):链表的介绍
java·开发语言·数据结构
影寂ldy1 小时前
C# HttpClient 分片下载、断点续传、暂停取消(完整项目知识点)
开发语言·c#
雪隐1 小时前
AI股票小助手10-我用代码管住自己的手:一个普通人的市场观察笔记
前端·人工智能·后端
独隅1 小时前
DevEco Code Plan+Build 双 Agent 协同开发效率实测
java·开发语言
KaMeidebaby2 小时前
卡梅德生物技术快报|抗体筛选:抗体筛选中的噬菌体展示四参数调优——从流程设计到数据验证
开发语言·前端·javascript
大黄说说2 小时前
接口频繁超时、报错?后端常见排查思路总结
开发语言·php
跨境小陈2 小时前
2026 年如何使用 Python 抓取 Reddit 数据
开发语言·网络·python
甲维斯2 小时前
Opus5.0首测,瘫坐沙发!效果,时间,token皆无敌!
前端·人工智能
LVZ2 小时前
Skill + PVM 绝了,AI 直接帮你搞定环境问题了
前端