Dragula 是轻量级跨列表拖拽库,需将同级容器传入初始化,手动监听 drop 等事件同步数据,注意 DOM 结构、框架响应式更新及移动端 touch 支持。

Dragula 是一个轻量级的拖拽库,适合实现多列表之间的元素拖拽(如看板式任务管理、多栏排序等)。它不依赖 jQuery,API 简洁,但需注意其默认行为和关键配置点。
初始化多个容器并启用跨列表拖拽
Dragula 默认支持多个容器间拖拽,只需将它们作为 containers 传入。关键在于所有目标列表必须是同一 Dragula 实例管理的“容器”,且结构上互为兄弟或同级 DOM 节点。
- 确保每个列表是独立的
<div class="list">或类似块级容器,不要嵌套在彼此内部 - 初始化时传入所有列表元素(NodeList 或数组):
const drake = dragula([
document.getElementById('list-a'),
document.getElementById('list-b'),
document.getElementById('list-c')
], {
// 可选:允许从任意容器拖出
moves: function (el, source, handle, sibling) {
return handle.classList.contains('drag-handle'); // 仅允许点击拖拽手柄时开始
}
});
监听拖拽事件,更新数据与 UI
Dragula 不自动同步数据,你需要手动处理 drag、drop、over、out 等事件来维护状态。
-
drag:元素被拿起,可临时禁用某些交互 -
drop:元素放入新容器,此时el已被 append 到target,应立即更新对应的数据数组 -
over/out:用于视觉反馈(如高亮目标容器)
drake.on('drop', function (el, target, source, sibling) {
const itemId = el.dataset.id;
const fromList = source.id;
const toList = target.id;
// 更新你的数据模型(例如:从 fromList 移除,加入 toList)
moveItem(itemId, fromList, toList);
// 可选:滚动到目标位置、保存到后端等
});
避免常见陷阱
多列表拖拽容易出问题的地方集中在 DOM 结构和事件干扰上:
- 不要在容器内使用
position: absolute或transform的子元素,会影响拖拽坐标计算 - 如果列表用了 Vue/React 等框架,Dragula 操作 DOM 后需主动触发视图更新(例如 Vue 中用
this.$forceUpdate()或响应式重赋值) - 移动端需额外引入
dragula-touch插件,否则 touch 事件不生效 - 若某列表禁止接收拖入,可在
accepts钩子中返回false:
drake.on('accepts', function (el, target, source, sibling) {
if (target.id === 'list-locked') return false;
});
样式与体验优化建议
Dragula 不提供默认样式,但可通过 CSS 类名增强反馈:
- Dragula 自动添加
gu-transit(拖拽中)、gu-mirror(镜像元素)、gu-source(原容器)等 class,可针对性写样式 - 给
.gu-transit加透明度或阴影,让拖拽更直观 - 在
over时给target添加gu-over类(需自己加逻辑),配合 CSS 高亮边框或背景

















