Dragula在Vue中拖拽后数据没更新怎么办?

A. 立顺 阅读 49

我在用 dragula 做一个任务看板,拖完卡片后 DOM 看起来移过去了,但 Vue 里的数组顺序根本没变,导致保存时还是原来的数据。我试过在 drake.on(‘drop’) 里手动 splice,但总对不上索引,有没有人遇到过类似问题?

<template>
  <div ref="container">
    <div v-for="(item, i) in tasks" :key="item.id" class="task-card">
      {{ item.text }}
    </div>
  </div>
</template>

<script>
import dragula from 'dragula'
export default {
  data() { return { tasks: [{ id: 1, text: 'A' }, { id: 2, text: 'B' }] } },
  mounted() {
    dragula([this.$refs.container])
  }
}
</script>
我来解答 赞 11 收藏
二维码
手机扫码查看
2 条解答
博主致远
试试看在 drake.on('drop') 里用 Vue.set 来更新数组,确保 Vue 能检测到变化。
mounted() {
const drake = dragula([this.$refs.container])
drake.on('drop', (el, target, source, sibling) => {
const fromIndex = Array.from(source.children).indexOf(el)
const toIndex = sibling ? Array.from(target.children).indexOf(sibling) : target.children.length
this.tasks.splice(toIndex, 0, this.tasks.splice(fromIndex, 1)[0])
})
}
点赞
2026-03-21 09:23
UI玉鑫
UI玉鑫 Lv1
这问题是 dragula 的老毛病了,它只管 DOM 操作,根本不鸟你 Vue 的响应式数据。

核心思路:drop 事件触发后,手动根据 DOM 的位置变化来更新数组。





关键点说下:

1. 给每个卡片加 :data-id="item.id",方便从 DOM 反查数据
2. drop 回调的 sibling 参数是重点,它是参照元素(插在它前面),用 Array.from(target.children).indexOf(sibling) 就能拿到新位置索引
3. 先 splice 删掉,再 splice 插入,顺序别搞反

还有个坑:如果是从一个列表拖到另一个列表,那处理方式又不一样了,你这个是单容器问题不大。

保存之前打个 console.log 看看数组顺序对不对,应该就 OK 了。
点赞
2026-03-16 18:10