React 拖拽实战指南:beautiful-react-hooks 中 useDrag 的用法、自定义拖拽图像与数据传递
前端开发工具【免费下载链接】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点击查看免费下载在 React 项目中实现可拖拽元素往往要手写draggable属性、dragstart/dragend监听器、组件卸载时的清理逻辑以及DataTransfer的数据序列化细节。beautiful-react-hooks提供的useDrag将这一整套流程收敛为一次 Hook 调用传入一个 DOM ref即可让元素获得原生拖拽能力并拿到一个表示是否正在被拖拽的布尔状态再通过dragImage、transfer等选项可自定义拖拽时显示的图像与传递给放置目标的数据。读完本文你将掌握useDrag的全部选项参数、三类典型用法基础拖拽、自定义拖拽图像、数据传递并能从源码层面理解其事件注册、draggable属性自动设置与监听器自动清理的完整实现机制。简介一行 Hook 启用元素拖拽useDrag接收一个指向 HTML 元素的引用通常来自 React 的useRef并让该元素变为可拖拽。Hook 返回一个布尔值表示元素当前是否正在被拖拽。官方文档docs/useDrag.md给出的三点价值主张负责将拖拽相关的事件监听器挂载到指定的目标元素上负责在组件卸载时移除这些监听器让你可以轻松实现可拖拽的业务逻辑。按需引入方式与包名对应关系可在 package.json 的exports字段中确认./useDrag同时提供 ESMdist/esm/useDrag.js、CJSdist/useDrag.js与类型声明dist/useDrag.d.ts三种产物因此支持beautiful-react-hooks/useDrag这种按子路径的引入方式也便于打包器做 tree-shaking。包的peerDependencies要求react 18.2.0 20.0.0使用时需保证项目 React 版本在该区间内。基础用法让元素可拖拽并跟踪拖拽状态第一个参数传入一个 DOM ref返回值即拖拽状态import { useRef } from react; import useDrag from beautiful-react-hooks/useDrag; const MyComponent () { const ref useRef(); const isDragged useDrag(ref); return ( DisplayDemo titleuseDrag div ref{ref} style{{ padding: 20px 0, background: isDragged ? #BE496E : #1D6C8B }} Draggable item... {isDragged spanis being dragged/span} /div /DisplayDemo ); }; MyComponent /示例中的DisplayDemo是官方文档演示用的容器组件实际项目中可替换为任意容器或直接去掉。这里有两个值得注意的机制均能由源码证实无需手动设置draggable属性。useDrag内部固定以isDraggable true调用useDragEvents见 src/useDrag.ts而useDragEvents在挂载时的useEffect中检查目标元素若其没有draggable属性则自动调用setAttribute(draggable, true)见 src/useDragEvents.ts。因此示例代码没有写draggable属性也能拖同时已自带该属性的元素不会被覆盖。isDragged只在dragstart与dragend两个时刻翻转。源码中onDragStart回调执行setIsDragging(true)onDragEnd回调执行setIsDragging(false)见 src/useDrag.ts它只回答是否处于拖拽进行中不提供拖拽坐标等更细粒度的信息——这一点在注意事项中会进一步展开。自定义拖拽图像dragImage 与偏移量默认情况下浏览器拖拽时显示的是元素自身的截图。如果希望拖拽时跟随鼠标的是一个自定义图片例如项目 Logo 或缩略图可以传入dragImage及其在光标处的偏移量import { useRef } from react; import useDrag from beautiful-react-hooks/useDrag; const MyComponent () { const ref useRef(); const isDragged useDrag(ref, { dragImage: https://beautifulinteractions.com/img/logo-colorful.svg, dragImageXOffset: 5, dragImageYOffset: 5, }); return ( DisplayDemo titleuseDrag div ref{ref} style{{ padding: 20px 0, background: isDragged ? #BE496E : #1D6C8B }} Draggable item... {isDragged spanis being dragged/span} /div /DisplayDemo ); }; MyComponent /从源码看src/useDrag.ts这段配置的落地逻辑是if (opts.dragImage event.dataTransfer) { const img new Image() img.src opts.dragImage event.dataTransfer.setDragImage(img, opts.dragImageXOffset ?? 0, opts.dragImageYOffset ?? 0) }即在dragstart事件中动态构造一个Image对象并交给dataTransfer.setDragImage()渲染。两个偏移量的默认值均为0由defaultOptions提供见 src/useDrag.ts其语义是图像左上角相对光标的像素偏移示例中的5, 5让图像中心大致对准光标位置避免图像左上角与光标重叠导致的贴边观感。拖拽数据传递transfer 与 transferFormatHTML5 拖放模型中可拖拽源负责往DataTransfer里写数据放置目标在drop事件中读取。useDrag通过transfer与transferFormat两个选项封装了这个过程import { useRef } from react; import useDrag from beautiful-react-hooks/useDrag; const MyComponent () { const ref useRef(); const isDragged useDrag(ref, { transfer: { id: item-id, foo: bar }, transferFormat: text/plain, }); return ( DisplayDemo titleuseDrag div ref{ref} style{{ padding: 20px 0, background: isDragged ? #BE496E : #1D6C8B }} Draggable item... {isDragged spanis being dragged/span} /div /DisplayDemo ); }; MyComponent /源码中的序列化与写入逻辑src/useDrag.ts为if (opts.transfer event.dataTransfer) { const data typeof opts.transfer object ? JSON.stringify(opts.transfer) : ${opts.transfer} event.dataTransfer.setData(opts.transferFormat ?? text, data) }由此可以明确transfer的类型与行为对应关系传入对象如{ id: item-id, foo: bar }时会被JSON.stringify序列化为 JSON 字符串后写入传入字符串或数字时直接以模板字符串转成文本写入transferFormat指定写入DataTransfer的 MIME 类型源码兜底值为textdefaultOptions.transferFormat见 src/useDrag.ts官方示例中显式使用了标准的text/plain。对应的放置目标侧可以用同库的 useDropZone 或在放置区的onDrop中通过event.dataTransfer.getData(text/plain)取回该字符串并JSON.parse还原。由于写入的始终是字符串对象 → JSON 字符串 → 放置端解析这一约定需要两端自行保持一致这是 HTML5 原生拖放模型本身的限制并非 Hook 缺陷。参数参考Types完整选项接口与函数签名如下继承自 docs/useDrag.md 的 Types 部分与 src/useDrag.ts 的源码定义一致import { type RefObject } from react; export interface UseDragOptions { dragImage?: string; dragImageXOffset?: number; dragImageYOffset?: number; transfer?: string | number | Recordstring, any; transferFormat?: string; } declare const useDrag: TElement extends HTMLElement(targetRef: RefObjectTElement, options?: UseDragOptions) boolean; export default useDrag;结合源码defaultOptions与setData的兜底逻辑各参数的默认值与语义整理如下参数类型默认值说明dragImagestring无不设置则使用元素自身截图拖拽时显示的自定义图像 URLdragImageXOffsetnumber0自定义图像相对光标的水平偏移像素dragImageYOffsetnumber0自定义图像相对光标的垂直偏移像素transferstring \| number \| Recordstring, any无不写数据拖拽时写入DataTransfer的数据对象会被 JSON 序列化transferFormatstringtext写入数据所用的 MIME 格式建议显式使用text/plain等标准类型另外从源码结构看src/useDrag.ts选项的合并方式是{ ...defaultOptions, ...(options || {}) }即未显式传入的字段会自动补齐默认值每个渲染都会重新注册捕获最新opts的回调因此后续渲染中更新选项对象对之后的下一次拖拽会生效。源码走读useDrag 底层是如何工作的useDrag的实现不到 50 行其核心是三层委托结构理解这条调用链能解释它的行为边界。第一层useDragsrc/useDrag.ts负责业务语义——状态翻转、dragImage设置、DataTransfer写入全部集中在onDragStart/onDragEnd两个回调里。第二层useDragEventssrc/useDragEvents.ts负责事件抽象。它基于useEvent批量构造了onDrag、onDrop、onDragEnter、onDragEnd、onDragExit、onDragLeave、onDragOver、onDragStart共 8 个回调设置器并以Object.freeze返回只读对象见 src/useDragEvents.ts。它还包含一道防御性校验若传入的 ref 不是标准的 React ref缺少current属性会直接抛出Unable to assign any drag event to the given ref错误src/useDragEvents.ts把传错 ref的问题暴露在渲染期而非事件期。第三层useEventsrc/useEvent.ts负责真正的事件绑定。它在useEffect中执行addEventListener并在 cleanup 函数中执行removeEventListener见 src/useEvent.ts——这正是文档中组件卸载时自动移除监听器承诺的实现来源。事件触发时原生事件会被转发到一个 ref 中缓存的最新回调而这个缓存机制由工厂函数 createHandlerSetter 提供。这里有一个对使用者很关键的设计约束createHandlerSetter的注释明确说明它返回的 setter 只是更新回调 ref设置回调 ref 不会强制组件重新渲染。因此回调必须在函数组件体内同步调用onDragStart(fn)、onDragEnd(fn)写在 render 过程中而不能放在setTimeout、Promise.then等异步上下文中——异步调用发生在事件监听建立流程之外回调无法被正确挂载。这也是同库useDragEvents文档反复强调的不要异步调用回调设置器的原因。从源码结构看这种渲染期注册 事件期读取 ref的模式同时避免了为每次拖拽重新绑定原生监听器是这套 Hooks 控制性能的手段之一。仓库内的测试用例 test/useDrag.spec.js 验证了基本契约以{ current: document.createElement(div) }作为 ref 渲染 Hook 后返回值必须是布尔值it(should return an object the state of the current dragging element, () { const targetRef { current: document.createElement(div) } const { result } renderHook(() useDrag(targetRef)) expect(result.current).to.be.an(boolean) })注意事项与能力边界它封装的是 HTML5 原生拖放而非基于 Pointer 事件的自定义拖拽。useDrag依赖dragstart/dragend事件与draggable属性因此受浏览器原生拖放模型的约束例如移动端浏览器对 HTML5 拖放的支持并不完整。它适合把元素拖到另一个放置区这类场景不适合实现需要逐帧跟手坐标的拖动交互。isDragged只表达状态不表达位置。Hook 不暴露clientX/clientY或偏移量如果业务需要元素跟着鼠标走的效果需要自行在drag事件基础上扩展或直接使用同库的 useDragEvents其文档中还给出了带放置区onDragOver/onDrop的完整示例。放置端需要配对 Hook。transfer写入的数据必须有一个读取方仓库中对应的放置端 Hook 是 useDropZone若只使用useDrag拖拽行为本身不受影响只是drop时读不到数据。不建议用底层事件 Hook 替代标准 propsuseDragEvents官方文档特别指出若组件已有onDragStart{handler}这类标准 React 拖拽 props 的用法应继续沿用标准 props 方案因为绕过 React SyntheticEvent 会损失相应性能见 docs/useDragEvents.md 的 What not to do 部分。何时选用 useDrag官方文档给出的使用判据很简洁当你需要基础的拖拽相关业务逻辑时。结合源码与同库 Hook 的分工可以把选型边界再具体化一些需求推荐 Hook让元素可拖拽 跟踪拖拽中状态 可选自定义图像/传数据useDrag需要drop、dragOver、dragEnter/Leave等完整事件集合来抽象自定义拖放逻辑useDragEvents需要一个放置区来接收拖放数据useDropZoneuseDrag本质上是useDragEvents的上层封装仅消费其中的onDragStart/onDragEnd因此当需求超出状态翻转 图像 传数据时向下切换到底层 Hook 是仓库内自然的升级路径而不必换用第三方拖拽库。赞分享前端开发工具【免费下载链接】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点击查看免费下载相关推荐Clypra基础操作指南10分钟学会视频剪辑的核心技巧Clypra基础操作指南10分钟学会视频剪辑的核心技巧 Clypra是一款基于Tauri、React和TypeScript构建的现代视频编辑器专注于提供免费音视频视频视频处理桌面应用React Beautiful DND 拖拽元素的自定义形状非矩形拖拽区域实现React Beautiful DND 拖拽元素的自定义形状非矩形拖拽区域实现 在使用React Beautiful DND构建拖放界面时默认的矩形拖拽区域自定义拖拽图层实战用 react-dnd 的 DragLayer 打造零闪烁的拖拽反馈自定义拖拽图层实战用 react dnd 的 DragLayer 打造零闪烁的拖拽反馈 react dnd 的浏览器后端依赖 HTML5 原生拖放 API而前端UI组件上一篇Prompt2Model高级配置教程自定义组件、API集成与多平台部署下一篇【亲测免费】 强大的动态壁纸工具SwayFX创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Windows 手动安装 CMake 3.30.3 绿色包:环境配置与避坑指南

Windows 手动安装 CMake 3.30.3 绿色包:环境配置与避坑指南

简介:CMake 3.30.3 Windows x86-64 官方安装包,面向在 64 位 Windows 平台上进行 C 开发的工程师与学习者,用于解决跨平台项目构建配置繁琐、编译流程难以自动化的问题。压缩包共 2000 个文件,以 1147 个 txt 与 853 个 html 为主…

2026/9/25 2:13:58 阅读更多 →
DShot协议原理与双向通信实战指南

DShot协议原理与双向通信实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 2:13:58 阅读更多 →
选SD-WAN服务商看什么?12项评估清单与9家代表厂商一览

选SD-WAN服务商看什么?12项评估清单与9家代表厂商一览

厂商信息为公开资料整理,截至 2026 年 9 月;排列顺序不构成排名。涉及性能、覆盖的数字为厂商口径,案例已脱敏,以书面承诺与实测为准。选 SD-WAN 设备和选 SD-WAN 服务商,是两件不同的事。设备可以放进实验室压测&…

2026/9/25 2:12:57 阅读更多 →

最新新闻

PaddleSeg 中的 MaskFormer:基于 Set Prediction 的语义分割实现与 ADE20k 训练实战

PaddleSeg 中的 MaskFormer:基于 Set Prediction 的语义分割实现与 ADE20k 训练实战

人工智能计算机视觉预训练 【免费下载链接】PaddleSeg Easy-to-use image segmentation library with awesome pre-trained model zoo, supporting wide-range of practical tasks in Semantic Segmentation, Interactive Segmentation, Panoptic Segmentation, Image Matting,…

2026/9/25 4:45:40 阅读更多 →
打造 security-audit-skill:让 AI 助手变身代码安全审计专家

打造 security-audit-skill:让 AI 助手变身代码安全审计专家

1. skill 是什么,以及为什么要专门做 security-audit-skill先花半分钟对齐一下概念。你可能已经被“agent skill”“claude skill”“codex skill”这些词轰炸过一阵子了,但如果让你一句话说清楚“skill 到底是个什么东西”,很多人其实还是懵…

2026/9/25 4:45:39 阅读更多 →
node-fetch v3 升级指南:从 v2 迁移到 Fetch 标准的破坏性变更与增强特性全解析

node-fetch v3 升级指南:从 v2 迁移到 Fetch 标准的破坏性变更与增强特性全解析

后端 【免费下载链接】node-fetch A light-weight module that brings the Fetch API to Node.js 项目地址: https://gitcode.com/gh_mirrors/no/node-fetch 点击查看 免费下载 node-fetch v3.x 是向 WHATWG Fetch Standard 全面看齐的一次重大重构:它提…

2026/9/25 4:45:39 阅读更多 →
AWS SDK for .NET (v3) 实战指南:用 S3 Conditional Requests 场景示例掌握 ETag 与时间条件请求

AWS SDK for .NET (v3) 实战指南:用 S3 Conditional Requests 场景示例掌握 ETag 与时间条件请求

示例工程教程后端 【免费下载链接】aws-doc-sdk-examples Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below. 项目地…

2026/9/25 4:45:39 阅读更多 →
Ghost Downloader 3 多协议下载器完整上手指南:五分钟从零跑通

Ghost Downloader 3 多协议下载器完整上手指南:五分钟从零跑通

Ghost Downloader 3 多协议下载器完整上手指南:五分钟从零跑通 【免费下载链接】Ghost-Downloader-3 The only downloader you need. 下载器的集大成者。 项目地址: https://gitcode.com/GitHub_Trending/gh/Ghost-Downloader-3 Ghost Downloader 3 是一个基…

2026/9/25 4:45:39 阅读更多 →
用树莓派+RTSP+夸克网盘,零成本搭建24小时监控存储与回放系统

用树莓派+RTSP+夸克网盘,零成本搭建24小时监控存储与回放系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 4:44:39 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →