Draggable插件系统完全指南:Collidable、Snappable如何按需扩展拖拽行为
【免费下载链接】draggableThe JavaScript Drag & Drop library your grandparents warned you about.项目地址: https://gitcode.com/gh_mirrors/dr/draggable
Draggable是一个功能强大的 JavaScript 拖放库,它的插件系统让你只需一行配置就能扩展拖拽行为。本篇指南带你快速了解如何通过 Collidable 和 Snappable 两大插件,按需求"拼装"出恰到好处的拖放体验,而不必自己造轮子。
为什么需要插件系统?
核心思路一句话:基础库负责"拖起来",插件负责"加行为"。
Draggable 初始化时会自动挂载 4 个默认插件,源码中定义在 Draggable.js:
| 默认插件 | 作用 |
|---|---|
| Mirror | 创建跟随鼠标的"镜像"副本,原元素留在原位 |
| Scrollable | 拖到边缘时自动滚动页面 |
| Focusable | 键盘可聚焦,提升可访问性 |
| Announcement | 为读屏软件播报拖放状态 |
而 Collidable、Snappable、ResizeMirror 等"增强插件"不会默认加载,你需要通过plugins选项手动开启——这正是"按需扩展"的精髓:用多少装多少,不增加不必要的体积和开销。
💡 所有插件都继承自统一基类 AbstractPlugin,只需实现
attach()(挂监听)和detach()(摘监听)两个方法,就能无缝接入拖拽生命周期。这也是自研插件的标准姿势。
Collidable 插件:给拖拽画"禁区"
🚧 想象你在设计看板,有些区域(比如侧边栏、固定工具条)不允许元素拖过去。Collidable 插件做的就是这件事:
- 指定哪些元素是碰撞对象(
collidables选项,支持 CSS 选择器字符串、元素数组或函数) - 拖拽进入禁区时,冻结镜像移动,元素"撞墙"停住
- 触发
collidable:in/collidable:out事件,方便你高亮墙面做视觉反馈
实现细节见 Collidable.js:它监听drag:move事件,用requestAnimationFrame节流碰撞计算,进入和离开各触发一次事件。
启用只需三步(完整文档见 Collidable/README.md):
import {Draggable, Plugins} from '@shopify/draggable'; const draggable = new Draggable(document.querySelectorAll('ul'), { draggable: 'li', collidables: '.other-list', // 声明"禁区" plugins: [Plugins.Collidable], // 按需开启插件 }); draggable.on('collidable:in', (evt) => { console.log('进入碰撞区域', evt.collidingElement); });📝 官方演示里还演示了碰撞时给"墙"加高亮样式的效果,参考 examples 的 Collidable 示例。
⚠️注意事项:当前碰撞检测基于鼠标光标位置(而非镜像元素),且仅配合Sortable、Swappable、Droppable使用效果最佳。
Snappable 插件:让镜像"啪"地吸附归位
📌 Snappable 模拟的是"吸附"手感:拖拽结束后直接隐藏镜像,而不是让它慢慢淡出,同时给源元素加上source:placed类,方便你写放置动画。
它没有配置项,效果开箱即用:
import {Sortable, Plugins} from '@shopify/draggable'; const sortable = new Sortable(document.querySelectorAll('ul'), { draggable: 'li', plugins: [Plugins.Snappable], }); // snap 事件支持取消——可以用来阻止吸附 sortable.on('snap:in', (evt) => { evt.cancel(); // 调用后不执行吸附 });和很多只能"通知"的事件不同,snap:in/snap:out是可取消事件(见 Snappable README 事件表),这意味着你可以在事件回调里做业务判断——比如"目标位置不合法就不吸附"——这在拖拽校验场景非常实用。
其他值得认识的插件
| 插件 | 适用场景 | 说明 |
|---|---|---|
| ResizeMirror | 网格布局拖拽 | 镜像会自动缩放到悬停目标的大小,视觉更自然 |
| SwapAnimation | Sortable 列表 | 交换位置时播放translate3d动画,可配时长与缓动 |
| SortAnimation | Sortable 网格 | 排序后所有元素整体平滑归位,支持横纵双向 |
插件全部从 src/Plugins/index.js 统一导出,plugins选项里想写几个就写几个;也可以在运行时用addPlugin()/removePlugin()动态装卸(API 见 Draggable README)。
新手常见问题 FAQ
Q1:插件和传感器(Sensors)有什么区别?插件扩展"拖拽中"的行为,传感器控制"怎么触发拖拽"(鼠标、触摸、Force Touch)。两者都在配置里以数组形式声明,但职责不同。
Q2:多个插件会冲突吗?通常不会,但动画类插件互斥:官方明确提示 SortAnimation 与 SwapAnimation 不要同时使用。
Q3:想自己写插件难吗?不难。继承 AbstractPlugin,在attach()里this.draggable.on('drag:move', ...)监听你关心的事件即可,事件清单可参考 Draggable 事件表。
小结
Draggable 的插件系统用"默认精简 + 按需增强"的设计,把复杂度留给了可选件:
- Collidable——声明禁区,拖拽撞墙自动停住,适合看板、布局编辑器
- Snappable——吸附式落位 + 可取消的 snap 事件,适合需要落位校验的场景
- 配合 ResizeMirror / SwapAnimation / SortAnimation 补全视觉体验
所有插件源码都集中在 src/Plugins/ 目录下,每个插件自带 README,建议对照本文把 Collidable 和 Snappable 各跑一遍示例(示例入口在 examples/src/content/Plugins/),五分钟就能掌握这套按需扩展的玩法。🚀
【免费下载链接】draggableThe JavaScript Drag & Drop library your grandparents warned you about.项目地址: https://gitcode.com/gh_mirrors/dr/draggable
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考