一、移动端事件分类
移动端事件主要分为以下几类:
1. 触摸事件(Touch Events)
触摸事件是移动设备特有的事件,用来处理用户通过触摸屏幕进行的操作。主要的触摸事件有:
touchstart
:手指触摸屏幕时触发。touchmove
:手指在屏幕上滑动时持续触发。touchend
:手指离开屏幕时触发。touchcancel
:当触摸被意外中断时(例如电话呼入、页面被打断),触发该事件。
触摸事件对应的监听方法:
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 元素。
示例:处理触摸事件
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 端事件的区别
-
触摸事件 vs 鼠标事件:
- 触摸事件是多点触控的,可以同时处理多个触点(手指),而鼠标事件是单点事件,只能跟踪一个光标。
- 移动端事件的触发顺序不同,常见顺序是:
touchstart
->touchmove
->touchend
,而鼠标事件的顺序是mousedown
->mousemove
->mouseup
。
-
点击延迟:
- 在移动设备上,当用户点击屏幕时,浏览器会等待大约 300ms 以确定用户是否会进行双击操作。这是移动浏览器的默认行为,用于处理双击缩放。解决方法一:但是现在已经解决了这个问题,只要设置了 viewport 即可:
解决方法二:使用移动端专属的触摸事件,不使用 click ,也就自然不存在 300ms 问题。<meta name="viewport" content="width=device-width, user-scalable=no">
- 在移动设备上,当用户点击屏幕时,浏览器会等待大约 300ms 以确定用户是否会进行双击操作。这是移动浏览器的默认行为,用于处理双击缩放。解决方法一:但是现在已经解决了这个问题,只要设置了 viewport 即可:
-
默认行为的不同:
- 移动端浏览器会根据触摸操作做出一些默认行为,比如页面滚动、双指缩放等,可能会与页面的自定义逻辑冲突。因此,通常需要阻止这些默认行为。
- 在触摸事件中可以通过
event.preventDefault()
来阻止默认的浏览器行为,例如页面滚动。
四、事件穿透
事件穿透(Event Penetration 或 Ghost Clicks) 是移动端上面一个非常有名的Bug,其出现场景为:有两层重叠的元素,上面的元素有 touch 事件(点击后要消失),下面是一个默认会触发 click 事件的元素(a、表单元素、带cick事件的壳素),此时点击上一层的元素,下一层也同样会被点击。
解决办法:
- 使用
preventDefault()
阻止默认行为。
element.addEventListener('touchend', function(event) {
event.preventDefault(); // 阻止默认的click行为
// 执行需要的逻辑
});
五、阻止默认事件带来的影响
移动端浏览器有一些默认行为,例如:
- 页面滚动:当用户在屏幕上滑动时,页面会跟随手指滚动。
- 双指缩放:用户可以通过双指操作缩放页面。
- 长按菜单:用户长按某些元素时,会弹出上下文菜单。
阻止默认事件的作用:
-
防止页面滚动:
在某些交互场景下,例如全屏的游戏或拖动元素时,默认的页面滚动行为会干扰用户体验。通过在touchmove
中调用event.preventDefault()
可以阻止页面滚动。element.addEventListener('touchmove', function(event) { event.preventDefault(); // 禁止页面跟随手指滚动 });
-
阻止双指缩放:
当页面需要固定缩放比例时,双指缩放会影响布局,可以通过以下方式阻止缩放行为:<meta name="viewport" content="width=device-width, user-scalable=no">
-
阻止长按弹出菜单:
用户长按图片或链接时,可能会弹出复制、保存等菜单,这对于某些 Web 应用来说是不必要的。可以通过阻止默认事件来禁用此功能。element.addEventListener('contextmenu', function(event) { event.preventDefault(); // 禁止长按弹出菜单 });
还有一些其他影响等等。
实际上,移动端进行开发时一上来就需要阻止所有的默认事件,后面的很多功能都需要我们自定义来实现。