【移动端】事件基础

一、移动端事件分类

移动端事件主要分为以下几类:

1. 触摸事件(Touch Events)

触摸事件是移动设备特有的事件,用来处理用户通过触摸屏幕进行的操作。主要的触摸事件有:

  • touchstart:手指触摸屏幕时触发。
  • touchmove:手指在屏幕上滑动时持续触发。
  • touchend:手指离开屏幕时触发。
  • touchcancel:当触摸被意外中断时(例如电话呼入、页面被打断),触发该事件。

触摸事件对应的监听方法:

javascript 复制代码
element.addEventListener('touchstart', handleTouchStart);
element.addEventListener('touchmove', handleTouchMove);
element.addEventListener('touchend', handleTouchEnd);
element.addEventListener('touchcancel', handleTouchCancel);

2. 手势事件(Gesture Events)

部分移动端浏览器还支持手势事件,例如两个手指同时在屏幕上缩放或旋转。主要的手势事件有:

  • gesturestart:手势操作开始时触发。
  • gesturechange:手势在进行时持续触发。
  • gestureend:手势操作结束时触发。

这些事件通常依赖于多指触控的场景,如缩放(pinch)和旋转(rotate),但由于浏览器的支持不一,实际开发中应用较少。

3. 鼠标事件(Mouse Events)

尽管移动设备没有物理鼠标,但大多数移动设备的浏览器仍然支持传统的鼠标事件。常见的鼠标事件包括:

  • mousedown :手指接触屏幕时(与 touchstart 类似)。
  • mousemove :手指在屏幕上滑动时(与 touchmove 类似)。
  • mouseup :手指离开屏幕时(与 touchend 类似)。
  • click:手指快速点击屏幕时触发(综合了触摸和鼠标操作)。

二、事件对象

在移动端,触摸事件与鼠标事件最大的不同在于事件对象(Event Object),触摸事件有自己独特的事件属性。每个触摸事件对象都会包含一些特殊的信息,用于描述触摸的详细情况。

触摸事件对象的常用属性:

  • touches:当前屏幕上所有触点的列表(多点触控时包含所有触摸点)。
  • targetTouches:当前与目标元素相关的触点列表。
  • changedTouches:自上次触摸事件以来发生变化的触点列表。

每个触点对象(Touch 对象)包含以下属性:

  • clientX / clientY:触点相对于浏览器窗口的 X 和 Y 坐标。
  • screenX / screenY:触点相对于屏幕的 X 和 Y 坐标。
  • target:触点目标的 DOM 元素。

示例:处理触摸事件

javascript 复制代码
element.addEventListener('touchstart', function(event) {
    const touch = event.touches[0]; // 获取第一个触点
    console.log('Touch position: ', touch.clientX, touch.clientY);
});

举个例子:

比如div1、diw2只有div2绑定了touchstart事件,第一次放下一个手指在dv2上,触发了touchstart事件,这个时候,三个集合的内容是一样的,都包含这个手指的touch,然后,再放下两个手指一个在div1上,一个在div2上,这个时候又会触发事件,但changedTouches里面只包含第二个第三个手指的信息,因为第一个没有发生变化,而targetTouches包含的是在第一个手指和第三个在 div2上的手指集合,touches包含屏幕上所有手指的信息,也就是三个手指。

三、与 PC 端事件的区别

  1. 触摸事件 vs 鼠标事件

    • 触摸事件是多点触控的,可以同时处理多个触点(手指),而鼠标事件是单点事件,只能跟踪一个光标。
    • 移动端事件的触发顺序不同,常见顺序是:touchstart -> touchmove -> touchend,而鼠标事件的顺序是 mousedown -> mousemove -> mouseup
  2. 点击延迟

    • 在移动设备上,当用户点击屏幕时,浏览器会等待大约 300ms 以确定用户是否会进行双击操作。这是移动浏览器的默认行为,用于处理双击缩放。解决方法一:但是现在已经解决了这个问题,只要设置了 viewport 即可:

      html 复制代码
      <meta name="viewport" content="width=device-width, user-scalable=no">

      解决方法二:使用移动端专属的触摸事件,不使用 click ,也就自然不存在 300ms 问题。

  3. 默认行为的不同

    • 移动端浏览器会根据触摸操作做出一些默认行为,比如页面滚动、双指缩放等,可能会与页面的自定义逻辑冲突。因此,通常需要阻止这些默认行为。
    • 在触摸事件中可以通过 event.preventDefault() 来阻止默认的浏览器行为,例如页面滚动。

四、事件穿透

事件穿透(Event Penetration 或 Ghost Clicks) 是移动端上面一个非常有名的Bug,其出现场景为:有两层重叠的元素,上面的元素有 touch 事件(点击后要消失),下面是一个默认会触发 click 事件的元素(a、表单元素、带cick事件的壳素),此时点击上一层的元素,下一层也同样会被点击。

解决办法:

  • 使用 preventDefault() 阻止默认行为。
javascript 复制代码
element.addEventListener('touchend', function(event) {
    event.preventDefault();  // 阻止默认的click行为
    // 执行需要的逻辑
});

五、阻止默认事件带来的影响

移动端浏览器有一些默认行为,例如:

  • 页面滚动:当用户在屏幕上滑动时,页面会跟随手指滚动。
  • 双指缩放:用户可以通过双指操作缩放页面。
  • 长按菜单:用户长按某些元素时,会弹出上下文菜单。

阻止默认事件的作用:

  1. 防止页面滚动

    在某些交互场景下,例如全屏的游戏或拖动元素时,默认的页面滚动行为会干扰用户体验。通过在 touchmove 中调用 event.preventDefault() 可以阻止页面滚动。

    javascript 复制代码
    element.addEventListener('touchmove', function(event) {
        event.preventDefault(); // 禁止页面跟随手指滚动
    });
  2. 阻止双指缩放

    当页面需要固定缩放比例时,双指缩放会影响布局,可以通过以下方式阻止缩放行为:

    html 复制代码
    <meta name="viewport" content="width=device-width, user-scalable=no">
  3. 阻止长按弹出菜单

    用户长按图片或链接时,可能会弹出复制、保存等菜单,这对于某些 Web 应用来说是不必要的。可以通过阻止默认事件来禁用此功能。

    javascript 复制代码
    element.addEventListener('contextmenu', function(event) {
        event.preventDefault(); // 禁止长按弹出菜单
    });

还有一些其他影响等等。

实际上,移动端进行开发时一上来就需要阻止所有的默认事件,后面的很多功能都需要我们自定义来实现。

相关推荐
毛骗导演3 分钟前
@tencent-weixin/openclaw-weixin 源码ContextToken 持久化改造:实现微信自定义消息发送能力
前端·架构
爱丽_3 分钟前
Pinia 状态管理:模块化、持久化与“权限联动”落地
java·前端·spring
进击的尘埃12 分钟前
从多仓到 Monorepo 的渐进式迁移:Git 历史保留、依赖收敛与缓存调优
javascript
SuperEugene31 分钟前
TypeScript+Vue 实战:告别 any 滥用,统一接口 / Props / 表单类型,实现类型安全|编码语法规范篇
开发语言·前端·javascript·vue.js·安全·typescript
我是永恒1 小时前
上架一个跨境工具导航网站
前端
电子羊1 小时前
Spec 编程工作流文档
前端
GISer_Jing1 小时前
从CLI到GUI桌面应用——前端工程化进阶之路
前端·人工智能·aigc·交互
还是大剑师兰特1 小时前
Vue3 报错:computed value is readonly 解决方案
前端·vue.js
leaves falling1 小时前
有效的字母异位词
java·服务器·前端
We་ct2 小时前
LeetCode 35. 搜索插入位置:二分查找的经典应用
前端·算法·leetcode·typescript·个人开发