
前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载导读usePointerSwipe是 VueUse 中基于原生 PointerEvents 的响应式滑动手势检测工具属于核心包vueuse/core的 Sensors传感器类别。它统一处理鼠标、触摸屏与触控笔三类指针输入无需区分touchstart/touchmove/touchend与mousedown/mousemove/mouseup两套事件体系即可实现滑动开始、滑动过程、滑动结束的完整手势生命周期追踪。读完本文你将掌握usePointerSwipe的全部配置项与返回值语义、其底层阈值判定与方向计算的源码原理并能基于它快速实现「滑动删除」「滑动切换卡片」等交互。usePointerSwipe 是什么usePointerSwipe提供基于 PointerEvents 的响应式滑动检测能力核心源码位于 packages/core/usePointerSwipe/index.ts并从 packages/core/index.ts 统一导出可通过import { usePointerSwipe } from vueuse/core直接使用。相比 VueUse 中基于触摸事件的 useSwipeusePointerSwipe的优势在于依赖PointerEvent一套事件体系同时覆盖鼠标mouse、触摸touch与触控笔pen三种指针类型通过setPointerCapture捕获指针指针按下后即使移出目标元素后续的pointermove与pointerup仍会重定向回目标滑动判定更稳定默认以passive: true注册监听器不阻塞滚动且自动为目标元素设置touch-action: pan-y允许页面纵向滚动、同时拦截横向滑动避免手势与滚动冲突。基础用法官方文档 packages/core/usePointerSwipe/index.md 给出的最小示例在模板元素上挂ref传给组合式函数即可拿到isSwiping是否正在滑动与direction滑动方向script setup langts import { usePointerSwipe } from vueuse/core import { useTemplateRef } from vue const el useTemplateRef(el) const { isSwiping, direction } usePointerSwipe(el) /script template div refel Swipe here /div /templatetarget参数类型为MaybeRefOrGetterHTMLElement | null | undefined即既可以直接传元素引用、ref对象也可以传返回元素的 getter 函数。内部通过toRef(target)来自vueuse/shared统一归一化为响应式引用并在元素挂载后自动注册事件监听。完整 API 与配置项UsePointerSwipeOptions接口定义于 packages/core/usePointerSwipe/index.ts各配置项及默认值如下配置项类型默认值说明thresholdnumber50触发滑动判定所需的最小位移像素位移未达到该值时不视为滑动onSwipeStart(e: PointerEvent) void—指针按下pointerdown时回调onSwipe(e: PointerEvent) void—滑动过程中pointermove且已超过阈值回调onSwipeEnd(e: PointerEvent, direction: UseSwipeDirection) void—滑动结束pointerup/pointercancel时回调携带最终方向pointerTypesPointerType[][mouse, touch, pen]允许监听的指针类型PointerType mouse \| touch \| pen见 packages/core/types.tsdisableTextSelectbooleanfalse是否在滑动时禁用文本选择设置user-select: none系列样式返回值UsePointerSwipeReturn见 packages/core/usePointerSwipe/index.ts返回值类型语义isSwipingReadonlyShallowRefboolean当前是否处于滑动状态位移已超过阈值directionReadonlyShallowRefUseSwipeDirection当前滑动方向取值为up \| down \| left \| right \| noneposStartDeepReadonlyPosition滑动起点坐标{ x, y }clientX/clientYposEndDeepReadonlyPosition滑动终点坐标{ x, y }distanceXReadonlyComputedRefnumber水平位移距离posStart.x - posEnd.x右滑为负值distanceYReadonlyComputedRefnumber垂直位移距离posStart.y - posEnd.y下滑为负值stop() void手动注销全部事件监听其中Position为{ x: number; y: number }定义于 packages/core/types.tsUseSwipeDirection类型则复用自useSwipe见 packages/core/useSwipe/index.ts。典型带配置示例script setup langts import { usePointerSwipe } from vueuse/core import { useTemplateRef } from vue const el useTemplateRef(el) const { isSwiping, direction, distanceX } usePointerSwipe(el, { threshold: 80, // 位移 80px 才判定为滑动 pointerTypes: [touch, mouse], // 忽略触控笔输入 disableTextSelect: true, // 滑动时禁止选中文本 onSwipeStart(e) { /* 记录手势开始 */ }, onSwipe(e) { /* 实时处理位移如驱动元素跟随 */ }, onSwipeEnd(e, direction) { /* 根据 direction 决定是否触发操作 */ }, }) /script源码级原理事件链路与方向判定usePointerSwipe的完整实现只有约 180 行逻辑非常紧凑核心链路如下。事件监听与指针捕获函数内部通过useEventListener来自 packages/core/useEventListener/index.ts注册后会在组件卸载时自动移除监听注册三组事件pointerdown校验事件类型后置isPointerDown true调用eventTarget.setPointerCapture(e.pointerId)捕获指针将clientX/clientY同时写入posStart与posEnd起点等于终点并触发onSwipeStartpointermove仅当isPointerDown为真时更新posEnd若位移首次超过阈值将isSwiping置为true此后每次移动触发onSwipepointerup/pointercancel同一监听器接收数组形式的多事件若正处于滑动状态则触发onSwipeEnd(e, direction.value)随后重置isPointerDown与isSwiping。所有监听器均以{ passive: true }注册见 packages/core/usePointerSwipe/index.ts保证不阻塞浏览器默认行为。stop()的实现即遍历内部保存的stops数组逐个注销监听见 packages/core/usePointerSwipe/index.ts可用于提前清理。阈值与方向计算位移与方向均基于 Vue 的computed计算属性实时推导packages/core/usePointerSwipe/index.tsconst distanceX computed(() posStart.x - posEnd.x) const distanceY computed(() posStart.y - posEnd.y) const isThresholdExceeded computed(() max(abs(distanceX.value), abs(distanceY.value)) threshold) const direction computed(() { if (!isThresholdExceeded.value) return none if (abs(distanceX.value) abs(distanceY.value)) return distanceX.value 0 ? left : right else return distanceY.value 0 ? up : down })方向判定遵循「谁位移大取谁」的原则水平位移绝对值更大时向左滑distanceX 0判定为left向右滑判定为right否则按垂直位移判定up/down。位移未达阈值时方向恒为none。指针类型过滤eventIsAllowedpackages/core/usePointerSwipe/index.ts负责事件过滤const eventIsAllowed (e: PointerEvent): boolean { const isReleasingButton e.buttons 0 const isPrimaryButton e.buttons 1 return options.pointerTypes?.includes(e.pointerType as PointerType) ?? (isReleasingButton || isPrimaryButton) ?? true }即显式传入pointerTypes时只处理指针类型匹配的事件未传入时默认接受主按钮按下buttons 1与按钮释放buttons 0的指针事件。样式副作用挂载后tryOnMounted来自vueuse/shared会自动对目标元素设置内联样式packages/core/usePointerSwipe/index.tstouch-action: pan-y允许纵向滚动、屏蔽触摸横向滚动保证横向滑动手势可被捕获若disableTextSelect: true追加-webkit-user-select: none、-ms-user-select: none与user-select: none滑动时防止误选中文本。与 useSwipe触摸事件方案的取舍如果只需要触摸屏手势、不关心鼠标与触控笔VueUse 还提供了基于TouchEvent的 useSwipe。两者对比维度usePointerSwipeuseSwipe事件体系PointerEvent鼠标/触摸/触控笔统一TouchEvent仅触摸方向类型复用UseSwipeDirection定义UseSwipeDirection本身监听选项固定passive: true支持passive配置默认truecapture: !passive非被动模式下可调用preventDefault拦截横向滚动指针捕获使用setPointerCapture依赖touches.length 1单指约束返回结构posStart/posEnd/distanceX/distanceYcoordsStart/coordsEnd/lengthX/lengthY需要鼠标与触控笔统一输入、或希望跨元素稳定追踪手势时选usePointerSwipe需要精细控制事件passive行为并在 touchmove 中主动preventDefault时选useSwipe。实战结合 distanceX 实现滑动切换仓库中的 packages/core/usePointerSwipe/demo.vue 提供了一个可直接参考的滑动卡片示例利用distanceX实时驱动元素位移与透明度并在onSwipeEnd中判断滑动距离是否超过容器宽度一半决定卡片是移出屏幕left: 100%、opacity: 0还是回弹复位script setup langts import { usePointerSwipe } from vueuse/core import { computed, shallowRef, useTemplateRef } from vue const target useTemplateRef(target) const container useTemplateRef(container) const containerWidth computed(() container.value?.offsetWidth) const left shallowRef(0) const opacity shallowRef(1) const { distanceX, isSwiping } usePointerSwipe(target, { disableTextSelect: true, onSwipe(e: PointerEvent) { if (containerWidth.value) { if (distanceX.value 0) { // 向左滑 const distance Math.abs(distanceX.value) left.value ${distance}px // 元素跟随手指位移 opacity.value 1.25 - distance / containerWidth.value // 随位移渐隐 } else { left.value 0 opacity.value 1 } } }, onSwipeEnd(e: PointerEvent, direction) { // 位移超过容器一半则滑出屏幕否则回弹 if (distanceX.value 0 containerWidth.value (Math.abs(distanceX.value) / containerWidth.value) 0.5) { left.value 100% opacity.value 0 } else { left.value 0 opacity.value 1 } }, }) /script template div refcontainer classrelative w-full h-[80px] overflow-hidden div reftarget :class{ transition-all duration-200 ease-linear: !isSwiping } :style{ left, opacity } Swipe /div /div /template要点提示distanceX posStart.x - posEnd.x因此向左滑为负值、向右滑为正值与视觉上的元素位移方向相反滑动过程中应关闭 CSS transition如示例中仅在!isSwiping时启用transition-all让元素跟手滑动结束再借助 transition 平滑回弹或滑出。测试验证与行为边界packages/core/usePointerSwipe/index.browser.test.ts 用 Vitest 模拟PointerEvent对行为做了完整验证可作为理解 API 语义的权威参照未超阈值位移小于threshold时onSwipeStart触发 1 次onSwipe与onSwipeEnd均不触发threshold is not exceeded用例超过阈值onSwipeStart/onSwipe/onSwipeEnd各触发一次onSwipeEnd携带方向right中途回退曾超过阈值后又回到阈值内onSwipe只在中途触发结束时onSwipeEnd携带方向noneisSwiping仍会先置真响应式pointerdown后isSwiping为false、direction为nonepointermove超阈值后isSwiping变真、direction更新为rightpointerup后isSwiping复位为false类型过滤设置pointerTypes: [touch]后派发鼠标指针事件不产生任何响应方向矩阵up / down / left / right四组坐标用例均被正确识别且onSwipeEnd收到对应方向stop 清理调用stop()后继续派发移动事件不再触发任何响应。从这些用例可以总结出三个容易被忽略的边界行为滑动结束后direction不会立即清空保留最后一次判定结果如right手势中途回退到阈值内时结束方向为none在未按下指针时派发pointermove会被忽略。小结usePointerSwipe以极小的实现体量单个 180 行左右的 index.ts封装了基于 PointerEvents 的完整滑动检测能力统一的指针类型过滤、指针捕获、阈值判定、方向计算与生命周期回调一应俱全。配合distanceX/distanceY响应式位移和isSwiping状态即可低成本实现滑动删除、滑动分页、手势导航等常见移动端与桌面端交互需要调整触发灵敏度时只需修改threshold需要限定输入设备时配置pointerTypes即可。赞分享前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载相关推荐AIRI 实战用 VueUse usePointerSwipe 构建基于 PointerEvents 的响应式滑动检测与拖拽交互AIRI 实战用 VueUse usePointerSwipe 构建基于 PointerEvents 的响应式滑动检测与拖拽交互 usePointerSwipAI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染Airi 项目 VueUse useSwipe 响应式滑动检测指南从 API 到移动端手势实战Airi 项目 VueUse useSwipe 响应式滑动检测指南从 API 到移动端手势实战 导读 useSwipe 是 VueUse 提供的响应式滑动检测AI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染如何用VueUse手势识别技术实现流畅的移动端交互useSwipe和usePointerSwipe终极指南如何用VueUse手势识别技术实现流畅的移动端交互useSwipe和usePointerSwipe终极指南 VueUse是一个功能强大的Vue组合式工具库提前端上一篇Apache Thrift Ruby 库完全指南从 gem 安装到客户端/服务端实战下一篇三步搞定黑苹果配置OpCore-Simplify让你的OpenCore配置变得简单快速创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考