前端开发工具【免费下载链接】beautiful-react-hooks A collection of beautiful and (hopefully) useful React hooks to speed-up your components and hooks development 项目地址https://gitcode.com/gh_mirrors/be/beautiful-react-hooks点击查看免费下载导读useSwipe是 beautiful-react-hooks 提供的一个用于追踪滑动手势swipe gesture状态的 React Hook它统一封装了鼠标事件与触摸事件让开发者无论面对移动端还是桌面端用户都能以同一套 API 读取当前滑动的方向、位移和次数。本文将以官方文档 docs/useSwipe.md 为主线结合仓库内 src/useSwipe.ts、src/shared/swipeUtils.ts 等源码实现与 test/useSwipe.spec.js 测试用例完整讲解它的使用方式、可配置项、返回值语义与底层工作原理读完后你将能直接在自己的组件中实现可复用的滑动交互如轮播、抽屉、手势引导等。为什么需要 useSwipe在 Web 应用中滑动是移动端最常见的交互但桌面端用户也会通过鼠标拖拽产生类似行为。手动处理这两套事件不仅代码冗余还容易遗漏边界情况。useSwipe主要解决以下痛点快速获取最近一次滑动数据无需自己维护坐标起点、位移增量等状态同时注册鼠标与触摸事件监听根据传入的 DOM ref 决定是绑定到目标元素还是全局 document组件卸载时自动移除监听由底层useEvent的useEffect清理逻辑保证避免内存泄漏将滑动逻辑抽象为可复用 Hook业务组件只需消费返回的SwipeState无需关心事件细节。这些动机在 docs/useSwipe.md 的 Why? 一节中有明确说明也是该 Hook 设计的目标。安装与引入beautiful-react-hooks 是一个按需导出的 ESM/CJS 双格式库见 package.json 中的exports字段你可以通过子路径直接引入单个 Hook避免打包进无关代码npm install beautiful-react-hooks # 或 yarn add beautiful-react-hooks代码中按需引入import useSwipe from beautiful-react-hooks/useSwipe;当前仓库的 peerDependencies 要求react 18.2.0 20.0.0使用前请确认你的 React 版本满足要求见 package.json。基础用法绑定到指定 DOM 元素useSwipe的第一个参数是一个 DOM ref。传入 ref 后鼠标与触摸事件将只会绑定在该元素上import { useRef, useState } from react; import useSwipe from beautiful-react-hooks/useSwipe; const SwipeReporter () { const ref useRef(); const swipeState useSwipe(ref); const showDetail swipeState.count 0 || swipeState.swiping; return ( DisplayDemo titleuseSwipe div ref{ref} style{{ padding: 20, background: #A1B5D8 }} Swipe me! {showDetail ( div pSwipe information:/p pIs swiping: {swipeState.swiping ? yes : no}/p pDirection: {swipeState.direction}/p pAlpha-x: {swipeState.alphaX}, Alpha-y: {swipeState.alphaY} /p pSwipe count: {swipeState.count}/p /div )} /div /DisplayDemo ); }; SwipeReporter /要点ref 必须指向一个真实存在的 DOM 节点HTMLElementHook 内部为泛型TElement extends HTMLElement返回的swipeState是受控状态对象随滑动过程实时更新因此组件会在滑动时自动重渲染showDetail用于在真正发生滑动后才展示细节面板避免初始空状态刷屏。全局事件模式不传 ref如果不传任何参数useSwipe会把监听器绑定到全局window.document上此时页面任意位置的滑动都会被捕获import { useRef, useState } from react; import useSwipe from beautiful-react-hooks/useSwipe; const SwipeReporter () { const swipeState useSwipe(); const showDetail swipeState.count 0 || swipeState.swiping; return ( DisplayDemo titleuseSwipe div style{{ padding: 20, background: #A1B5D8 }} Swipe everywehere you want! {showDetail ( div pSwipe information:/p pIs swiping: {swipeState.swiping ? yes : no}/p pDirection: {swipeState.direction}/p pAlpha-x: {swipeState.alphaX}, Alpha-y: {swipeState.alphaY} /p pSwipe count: {swipeState.count}/p /div )} /div /DisplayDemo ); }; SwipeReporter /从源码看这一行为由底层事件 Hook 保证在 useMouseEvents.ts 与 useTouchEvents.ts 中当targetRef未提供时会回退为{ current: window.document }从而将事件全局绑定到 document。全局模式的典型场景整页手势导航如翻页、返回、全屏滑动手势统计等。Options 配置项详解useSwipe的第二个参数是可选配置对象官方文档给出了三个核心选项而源码类型定义中还有一个额外的passive字段配置项类型默认值说明directionboth \| horizontal \| verticalboth允许滑动的方向horizontal/vertical会过滤另一方向的位移thresholdnumber见下方说明触发滑动中状态所需的最小位移像素数preventDefaultbooleantrue是否在滑动过程中调用event.preventDefault()与event.stopPropagation()passivebooleanundefined透传给addEventListener的passive选项用于优化滚动性能关于threshold默认值的说明官方文档标注为15而当前仓库源码 src/useSwipe.ts 中useSwipe自身的默认值是10与此同时useHorizontalSwipe与useVerticalSwipe两个快捷变体见 src/useHorizontalSwipe.ts、src/useVerticalSwipe.ts的默认阈值则是15。由于文档与源码存在版本差异建议在实际项目里显式指定threshold不依赖默认值以保证行为符合预期。带配置的完整示例import { useRef, useState } from react; import useSwipe from beautiful-react-hooks/useSwipe; const SwipeReporter () { const ref useRef(); const options { direction: horizontal, threshold: 10, preventDefault: true }; const swipeState useSwipe(ref, options); const showDetail swipeState.count 0 || swipeState.swiping; return ( DisplayDemo titleuseSwipe div ref{ref} style{{ padding: 20, background: #A1B5D8 }} Swipe me, horizontally... {showDetail ( div pSwipe information:/p pIs swiping: {swipeState.swiping ? yes : no}/p pDirection: {swipeState.direction}/p pAlpha-x: {swipeState.alphaX}, Alpha-y: {swipeState.alphaY} /p pSwipe count: {swipeState.count}/p /div )} /div /DisplayDemo ); }; SwipeReporter /各选项的源码级行为direction在 src/useSwipe.ts 的continueSwipe中按三种模式分别处理——both模式下横纵位移任一超过阈值即触发滑动horizontal只关注alpha[0]vertical只关注alpha[1]且单向模式下另一轴位移会被强制置 0threshold与Math.abs(alpha)比较用于过滤手指/鼠标抖动产生的微小位移避免误触发preventDefault为true时在startSwipe、continueSwipe、endSwipe三处都会调用event.preventDefault()和event.stopPropagation()见 src/useSwipe.ts可阻止页面滚动等默认行为但也意味着会打断页面滚动需按场景取舍passive传入 useMouseEvents.ts 与 useTouchEvents.ts 后透传给useEvent最终作为AddEventListenerOptions传给addEventListener。注意当passive: true时浏览器会忽略preventDefault()调用两者不要同时依赖。返回值 SwipeState 语义Hook 每次渲染返回一个SwipeState对象初始值为{ swiping: false, direction: undefined, alphaX: 0, alphaY: 0, count: 0 }见 src/useSwipe.ts字段类型含义swipingboolean当前是否正处于滑动中位移已超过阈值directionright \| left \| down \| up最近一次滑动的方向未滑动时为undefinedalphaXnumber起始点与当前点的横向位移差起始点 x − 当前点 xalphaYnumber起始点与当前点的纵向位移差起始点 y − 当前点 ycountnumber已经完成的滑动次数值得注意的语义细节alphaX/alphaY是带符号的位移量负值代表手指向右/向下移动方向判定正是基于其符号见下文源码分析count只在一次滑动结束时递增mouseup/touchend/mouseleave/touchcancel滑动中途不会变化因此常用来判断是否完成过至少一次滑动。源码级原理手势生命周期与方向判定三阶段事件流程从 src/useSwipe.ts 可以看出Hook 内部把一次滑动拆成三个阶段分别映射到鼠标/触摸事件对阶段处理函数绑定事件核心职责开始startSwipemousedown/touchstart记录起始点坐标到startingPointRef进行continueSwipemousemove/touchmove计算位移差超过阈值后更新swiping、alphaX/alphaY、direction结束endSwipemouseup/touchend以及mouseleave/touchcancel若正在滑动则递增count并复位swiping重置起始点其中mouseleave与touchcancel的绑定是为了处理手指/鼠标滑出元素或系统中断触摸的边界情况保证状态始终能复位不会卡在swiping: true。位移与方向的计算坐标提取与方向判定集中在 src/shared/swipeUtils.tsgetPointerCoordinates优先读取event.touches[0]的clientX/clientY触摸事件否则回退到MouseEvent的clientX/clientY从而统一两种事件源getHorizontalDirection(alpha)alpha 0返回right否则返回leftgetVerticalDirection(alpha)alpha 0返回down否则返回upgetDirection(currentPoint, startingPoint, alpha)比较横纵位移的绝对值位移较大的轴决定最终方向斜向滑动时给出主方向。方向含义速查由于alpha 起始点 − 当前点手指向右滑动时alphaX 0因此返回right手指向下滑动时alphaY 0返回down语义直观。状态更新的防抖优化源码在每次更新前通过isEqual比较新旧状态src/useSwipe.ts只有swiping、direction、count、alphaX、alphaY任一发生变化才调用setState避免高频mousemove/touchmove触发无意义重渲染。事件绑定与自动清理机制useSwipe并不直接调用addEventListener而是组合了两个更底层的事件 HookuseMouseEvents.ts 提供onMouseDown/onMouseMove/onMouseUp/onMouseLeave等回调注册器useTouchEvents.ts 提供onTouchStart/onTouchMove/onTouchEnd/onTouchCancel回调注册器两者最终都经由 useEvent.ts 的useEffect完成监听注册与清理useEffect的依赖包含eventName、target.current与options并在 cleanup 中调用removeEventListener。因此当组件卸载、ref 指向的 DOM 被替换或事件配置变化时旧监听会被自动移除这正是文档中自动移除监听承诺的实现基础。快捷变体useHorizontalSwipe 与 useVerticalSwipe仓库为最常见的单向滑动提供了两个语法糖useHorizontalSwipe.ts内部强制direction: horizontal默认阈值 15useVerticalSwipe.ts内部强制direction: vertical默认阈值 15。它们与useSwipe返回完全相同的SwipeState结构适合明确只需要横向或纵向滑动判断的场景写法更简洁、语义更清晰import useHorizontalSwipe from beautiful-react-hooks/useHorizontalSwipe; import useVerticalSwipe from beautiful-react-hooks/useVerticalSwipe;测试验证仓库在 test/useSwipe.spec.js 中为三个相关 Hook 编写了单元测试关键断言包括useSwipe是命名以use开头的 Hook 函数通过assertHook工具校验调用useSwipe()后返回值是一个包含swiping、direction、alphaX、alphaY、count五个键的对象useHorizontalSwipe与useVerticalSwipe同样返回上述五键结构。你可以通过以下命令在本地复跑测试确认行为见 package.json 的scriptsnpm install npm test使用建议与注意事项明确指定threshold文档默认值15与源码默认值10存在差异生产中建议显式传入避免版本差异导致的手感不一致按需选择绑定方式传入 ref 将手势限制在局部元素适合卡片、轮播不传 ref 则为全局监听适合整页手势但注意避免与页内其他拖拽交互冲突preventDefault与滚动preventDefault: true会阻止页面滚动与事件冒泡若你的目标元素本身需要可滚动应谨慎开启或搭配passive选项按需组合状态驱动渲染swipeState是 React 状态高频移动时会触发重渲染配合isEqual优化虽已减少无效更新但若追求极致性能可在回调中消费数据而非直接渲染全量状态TypeScript 友好useSwipeTElement extends HTMLElement为泛型设计UseSwipeOptions与SwipeState接口均已导出见 src/useSwipe.ts可在类型安全的前提下传入RefObjectHTMLElement。延伸阅读官方文档docs/useSwipe.md核心实现src/useSwipe.ts方向与坐标工具src/shared/swipeUtils.ts底层事件 Hooksrc/useEvent.ts、src/useMouseEvents.ts、src/useTouchEvents.ts测试用例test/useSwipe.spec.js若你的交互需要更细粒度的事件级控制而非聚合状态可以进一步了解仓库中同族的 useSwipeEvents、useTouch 与 useTouchEvents 文档。赞分享前端开发工具【免费下载链接】beautiful-react-hooks A collection of beautiful and (hopefully) useful React hooks to speed-up your components and hooks development 项目地址https://gitcode.com/gh_mirrors/be/beautiful-react-hooks点击查看免费下载相关推荐beautiful-react-hooks 中的 useHorizontalSwipe横跨桌面与移动端的横向滑动手势 Hookbeautiful react hooks 中的 useHorizontalSwipe横跨桌面与移动端的横向滑动手势 Hook 在 beautiful rea前端开发工具跨平台资源嗅探工具res-downloader三步解决网络资源获取难题跨平台资源嗅探工具res downloader三步解决网络资源获取难题 在数字内容创作日益普及的今天你是否曾为获取无水印视频素材而烦恼或者因无法批量下载在桌面应用网络音视频QQ空间历史说说还能找回来吗GetQzonehistory扫码一次5分钟恢复十年存档QQ空间历史说说还能找回来吗GetQzonehistory扫码一次5分钟恢复十年存档 QQ官方从未提供批量导出入口你发过多年的说说正悄悄散落在一个没有网页爬虫数据分析上一篇为什么选择Enduro.js轻量级Node.js CMS的优势分析下一篇learn-claude-code s15把 25 个工具、权限、记忆、任务、团队与 MCP 装进同一个 while True —— Integrated Harness 集成运行时详解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
