Draggable DragSensor 指南:用原生 HTML5 Drag  Drop API 驱动拖拽
Draggable DragSensor 指南用原生 HTML5 Drag Drop API 驱动拖拽【免费下载链接】draggableThe JavaScript Drag Drop library your grandparents warned you about.项目地址: https://gitcode.com/gh_mirrors/dr/draggable导读DragSensor 是 Shopify Draggable 拖拽库中一个特殊的传感器Sensor它不监听模拟的鼠标/触摸事件而是直接接管浏览器原生的 HTML5 Drag and Drop API把dragstart、dragover、dragend等原生拖拽事件翻译成 Draggable 统一的drag:start、drag:move、drag:stop传感器事件。本文以 DragSensor 官方文档 为主体结合 DragSensor 源码、基类 Sensor 与 单元测试带你掌握它的 API、配置项、工作原理、已知局限以及正确的接入方式。DragSensor 是什么接管原生浏览器拖拽在 Draggable 的传感器体系中MouseSensor 和 TouchSensor 通过监听mousedown/mousemove/touchstart等指针事件来模拟拖拽因此 Draggable 可以完全掌控整个拖拽过程并创建自己的视觉镜像Mirror。而DragSensor走的是另一条路线它捡起picks up浏览器原生的拖拽事件dragstart、dragover、dragend、drop、mousedown在containers指定的容器元素上触发以下 Draggable 传感器事件drag:startdrag:movedrag:stop这三个事件类型在 SensorEvent.ts 中定义为DragStartSensorEvent、DragMoveSensorEvent、DragStopSensorEvent均继承自SensorEvent携带clientX、clientY、target、container、originalSource、originalEvent等标准化属性。默认不启用文档开头有一句关键提示Draggable does not use this sensor by defaultDraggable 默认不使用此传感器。这在 Draggable.js 中有直接证据static Sensors {MouseSensor, TouchSensor};Draggable 静态挂载的默认传感器只有MouseSensor与TouchSensor。DragSensor虽然被 Sensors/index.js 导出但需要开发者显式传入sensors配置才会被激活。API构造、挂载与卸载new DragSensor(containers, options): DragSensor构造函数签名如下new DragSensor(containers: HTMLElement[]|NodeList|HTMLElement, options: Object): DragSensorcontainers传感器要监听的容器可以是HTMLElement数组、NodeList或单个HTMLElement。基类 Sensor 构造函数 会将其展开为数组[...containers]并把options浅拷贝到this.options。传感器事件始终在容器元素上触发trigger方法通过element.dispatchEvent派发见 Sensor.js#L111-L119外部监听时需在容器上绑定。dragSensor.attach(): void把传感器事件监听器挂到 DOM 上。对 DragSensor 而言attach()只做一件事attach() { document.addEventListener(mousedown, this[onMouseDown], true); }即在捕获阶段监听document上的mousedown作为整个拖拽流程的入口见 DragSensor.js#L66-L68。dragSensor.detach(): void与attach()对称移除mousedown捕获监听detach() { document.removeEventListener(mousedown, this[onMouseDown], true); }Options 配置项DragSensor 与 MouseSensor 共享基类Sensor的选项解析逻辑但文档只明确了两个配置项draggable {String}指定containers内可拖拽元素的 CSS 选择器。mousedown时源码用closest(target, this.options.draggable)向上查找命中元素const originalSource closest(target, this.options.draggable); if (!originalSource) { return; }只有当点击命中draggable选择器时传感器才会继续DragSensor.js#L210-L214。delay {Number}文档描述为延迟触摸开始delay touch start但从源码看它的真实语义更精确延迟把draggable属性写到源元素上从而延迟原生拖拽的启动。mousedown后源码会启动一个定时器this.mouseDownTimeout setTimeout(() { originalSource.draggable true; this.draggableElement originalSource; }, this.delay.drag);关键点是this.delay.drag。基类 Sensor.js#L1-L5 定义了默认延迟表const defaultDelay { mouse: 0, drag: 0, touch: 100, };calcDelaySensor.js#L127-L153支持三种传法不传三个键全部取默认值drag为0传数字三个键统一取该数值传对象如{drag: 200, touch: 100}缺省键回落默认值。因此若要长按才进入拖拽应配置delay: {drag: 200}这类对象形式。测试 DragSensor.test.js#L175-L178 用DRAG_DELAY验证了延迟后触发drag:start与延迟前松开鼠标不触发两个行为。注意由于draggable属性是延迟后才写上的在定时器触发前快速松开鼠标拖拽不会启动mouseup会调用reset()清除定时器与监听器见 DragSensor.js#L245-L272。测试does not trigger drag:start event releasing mouse before timeout正是对这一行为的回归验证DragSensor.test.js#L101-L124。源码中还支持的其它选项虽然文档只列出两个选项但从源码可以看到 DragSensor 还会用到基类继承下来的选项handle {String}指定拖拽手柄选择器。mousedown时若options.handle存在且点击目标不在手柄内直接返回DragSensor.js#L202-L208。type {String}拖拽允许的效果类型会被写入dataTransfer。dragstart时设置event.dataTransfer.effectAllowed this.options.typedragover时设置event.dataTransfer.dropEffect this.options.typeDragSensor.js#L85、#L140。distance无效见下文 Caveats。事件触发流程从 mousedown 到 drag:stop结合源码一次完整的 DragSensor 拖拽生命周期如下mousedown捕获[onMouseDown]先排除 Firefox 中表单控件/contenteditable的已知 bugbugzilla 739071 注释保留在 DragSensor.js#L190-L193随后依次校验容器命中、handle约束、draggable命中若命中的是原生可拖拽元素链接、图片等draggable属性为真的元素会先将其draggable置为false暂存再注册mouseup/dragstart/dragover/dragend/drop监听并按delay.drag启动定时器。dragstart[onDragStart]先写入dataTransfersetData(text, )注释标明Firefox 需要 text 键IE 需要该写法用document.elementFromPoint定位目标构造DragStartSensorEvent并通过setTimeout(..., 0)触发给drag:start的取消留出机会事件被cancel()时dragging置为false。dragover仅当this.dragging为真时触发DragMoveSensorEventdrag:move未取消则preventDefault()并设置dropEffect保证浏览器持续允许放置。dragend / dropdragend触发DragStopSensorEventdrag:stop随后调用reset()清理drop处理器仅preventDefault()阻止浏览器默认行为。reset清除定时器与全部临时监听并把nativeDraggableElement、draggableElement的draggable属性逐一还原保证 DOM 不被污染。Draggable 核心Draggable.js#L422-L495在捕获阶段监听drag:start等传感器事件再对外触发业务层的DragStartEvent/DragMoveEvent/DragStopEvent你可以在draggable.on(drag:start, ...)中做业务处理。在 Draggable 中使用 DragSensor文档给出的接入示例import {Draggable, Sensors} from shopify/draggable; const draggable new Draggable(containers, { sensors: [Sensors.DragSensor], }); // Remove default mouse sensor draggable.removeSensor(Sensors.MouseSensor);两点补充说明依据 Draggable.jssensors选项传入的传感器会与默认的MouseSensor、TouchSensor共存构造函数在 Draggable.js#L179-L184 合并defaultSensors与options.sensors。由于原生拖拽与鼠标模拟拖拽可能互相干扰文档示例紧接着用draggable.removeSensor(Sensors.MouseSensor)移除默认鼠标传感器removeSensor 实现实践中通常也应如此必要时同样移除TouchSensor。传感器实例由addSensor用new Sensor(this.containers, this.options)创建并自动attach()Draggable.js#L257-L266所以draggable:start监听已由框架接线业务层无需手动attach()。Known issues没有镜像Mirror原生拖拽 API 的代价写在文档的 Known issues 一节DragSensor 使用原生 Drag and Drop API因此 Draggable 不会为它创建镜像对镜像的控制也更少。原因很直接浏览器在dragstart后会自动绘制一张半透明快照跟随光标系统级拖拽图像这张图像不受 JavaScript 完全控制Draggable 的 Mirror 插件 所实现的克隆元素、动画、样式跟随等能力在这一传感器下无法完整生效。如果你的交互依赖镜像效果例如排序动画、占位样式应优先考虑默认的 MouseSensor/TouchSensor。Caveatsdistance 选项无效文档末尾列出关键限制distance选项在 DragSensor 下不生效。distance的本意是指针移动超过指定距离后才开始拖拽见 MouseSensor 文档 的说明。但原生拖拽的启动由浏览器在dragstart时决定DragSensor 无法在按下—移动—达到阈值—才启动之间插入控制逻辑因此该选项被忽略。draggable命中判断、delay.drag延迟与handle约束是它在启动阶段仅有的可调手段。测试覆盖行为即规范DragSensor.test.js 用沙箱 DOM 与模拟事件流验证了核心契约可直接作为使用参考拖拽流程按下 → 延迟 → dragstart → dragover → dragend → 松开依次触发drag:start、drag:move、drag:stopL71-L152监听drag:start并调用event.detail.cancel()可以取消整次拖拽L84-L99点击非draggable命中的元素不触发drag:startL154-L172设置delay后延迟前松开鼠标不会触发任何拖拽事件L195-L219。总结与选型建议DragSensor 适合原生拖拽体验可接受、且希望省去自绘镜像成本的场景例如简单的列表重排、文件拖拽入口等它的取舍非常清晰优势直接复用浏览器成熟的拖放实现代码量小dataTransfer可携带数据为跨容器甚至跨页面放置留了可能代价无 Draggable 镜像、无distance阈值、对拖拽过程的自定义能力弱于基于指针事件模拟的默认传感器。若要精细控制拖拽视觉与交互镜像、排序动画、吸附等请使用默认的 MouseSensor/TouchSensor若仅需能拖就行或需要与原生放置目标协作再把 DragSensor 通过sensors选项接入并按文档示例移除冲突的默认传感器。【免费下载链接】draggableThe JavaScript Drag Drop library your grandparents warned you about.项目地址: https://gitcode.com/gh_mirrors/dr/draggable创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

面试被问okt原理答不上?3分钟源码解析带你跑赢性能瓶颈

面试被问okt原理答不上?3分钟源码解析带你跑赢性能瓶颈

面试被问okt原理答不上?3分钟源码解析带你跑赢性能瓶颈 上周刚结束一场后端面试,候选人代码写得挺溜,但面试官只问了一句:“你的 Token 生成逻辑里, okt 这个字段是干嘛的?为什么每次请求都要重新计算?”…

2026/9/21 22:03:21 阅读更多 →
Egg 运行环境(Server Env)机制详解:EGG_SERVER_ENV、config/env 与 NODE_ENV 的完整使用指南

Egg 运行环境(Server Env)机制详解:EGG_SERVER_ENV、config/env 与 NODE_ENV 的完整使用指南

Egg 运行环境(Server Env)机制详解:EGG_SERVER_ENV、config/env 与 NODE_ENV 的完整使用指南 【免费下载链接】egg 🥚🥚🥚🥚 Born to build better enterprise frameworks and apps with Node.j…

2026/9/21 22:03:21 阅读更多 →
uni-app X WebSocket 通信指南:connectSocket 全局 API 与 SocketTask 详解

uni-app X WebSocket 通信指南:connectSocket 全局 API 与 SocketTask 详解

uni-app X WebSocket 通信指南:connectSocket 全局 API 与 SocketTask 详解 【免费下载链接】uni-app A cross-platform framework using Vue.js 项目地址: https://gitcode.com/gh_mirrors/un/uni-app 本文基于 uni-app 开源仓库中 docs/api/websocket.md 文…

2026/9/21 22:03:21 阅读更多 →

最新新闻

华为机试题实战:5个高频面试题代码解析与避坑指南

华为机试题实战:5个高频面试题代码解析与避坑指南

华为机试题实战:5个高频面试题代码解析与避坑指南 看了一堆教程还是不会写项目?别急,问题往往出在练习方式上。华为机试不是背题,而是考察你能否在限定时间内解决实际问题。这里整理了5道 高频面试题 ,带你从零搭建解题框架,直接上手写代码。…

2026/9/22 0:03:42 阅读更多 →
AllData集成Crater:构建异构算力资源池,实现训推一体化

AllData集成Crater:构建异构算力资源池,实现训推一体化

每次数据平台版本更新,我最关心的反而不是那些花哨的BI报表功能,而是底层算力这块有没有实质动作。这次AllData数据中台宣布集成开源项目Crater,方向算是踩在了大模型时代的命门上——把GPU、CPU、内存、磁盘这些原本分散的异构算力资源统一纳…

2026/9/22 0:03:42 阅读更多 →
微信拉黑后删除避坑指南:从入门到精通的实战经验

微信拉黑后删除避坑指南:从入门到精通的实战经验

微信拉黑后删除避坑指南:从入门到精通的实战经验 官方文档里关于消息队列状态同步的章节写得像天书,翻了三页还没搞懂缓存失效机制。很多应届生刚接手业务,总被【微信拉黑后删除】这种边缘场景搞得头秃,以为只是删个好友这么简单。其实这里的水深得很,涉…

2026/9/22 0:03:42 阅读更多 →
3个血泪坑:四级怎么算分完整示例避坑指南

3个血泪坑:四级怎么算分完整示例避坑指南

3个血泪坑:四级怎么算分完整示例避坑指南 看了一堆教程还是不会写项目?别怪自己笨,是那些教程只教你“怎么算”,没教你“怎么落地”。今天这篇关于 四级怎么算分 的 完整示例…

2026/9/22 0:03:42 阅读更多 →
漫天花雨特效踩坑全记录:3个致命错误与完整示例

漫天花雨特效踩坑全记录:3个致命错误与完整示例

漫天花雨特效踩坑全记录:3个致命错误与完整示例 官方文档翻了三遍还是报错?别慌,不是你笨,是文档太碎,抓不住重点。 做前端特效最怕这种"漫天花雨"效果,看着简单,一写代码就炸。 今天直接上 完整示例…

2026/9/22 0:03:42 阅读更多 →
3天搞定CK1997:图解原理带你从零搭建高可用后端

3天搞定CK1997:图解原理带你从零搭建高可用后端

3天搞定CK1997:图解原理带你从零搭建高可用后端 版本升级后 API 全变了,这大概是很多开发者接手老项目时的第一反应。以前熟悉的接口调用方式,在 CK1997…

2026/9/22 0:02:42 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

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

周新闻

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

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

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

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

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

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

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

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

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

2026/9/21 4:51:05 阅读更多 →

月新闻

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

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

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

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

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

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

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

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

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

2026/9/19 23:35:34 阅读更多 →