Sortable.js 拖拽后顺序变了但数据没更新怎么办?
我用 Sortable.js 做了一个列表拖拽排序,视觉上元素位置确实变了,但我发现背后的数组数据根本没跟着变。我试过在 onEnd 回调里手动 splice 更新数组,但索引总是对不上,拖两下就乱了。
这是我的初始化代码:
new Sortable(document.getElementById('list'), {
onEnd: function (evt) {
const oldIndex = evt.oldIndex;
const newIndex = evt.newIndex;
// 我在这里操作 this.myArray,但结果不对
}
});
是不是我取索引的方式有问题?或者应该用别的方法同步数据?
Sortable.js 的 onEnd 回调里的 oldIndex 和 newIndex 是基于当前 DOM 的索引,理论上和数组索引应该是一一对应的(前提是你初始化时数组和 DOM 顺序一致)。你用 splice 操作思路是对的,但可能细节上有点问题。
核心解决方法很简单,就两步:
这里有个关键点:你不需要关心索引谁大谁小,因为 splice(1, 0, item) 是在指定位置插入,原位置的元素会自动后移。
如果你还是感觉索引对不上,可能是下面几个原因:
原因一:数组和 DOM 初始顺序不一致
你初始化 Sortable 之前,DOM 里的元素顺序和 this.myArray 的顺序不一样。比如 DOM 是 [A, B, C],但数组是 [B, A, C],那索引肯定乱套。确保它们一开始就是同步的。
原因二:重复调用初始化
如果你的页面会重新渲染列表,每次都 new Sortable() 会导致事件绑定叠加,拖一次触发多次回调。可以在初始化前先销毁旧的实例:
原因三:没有用箭头函数保持 this
你的回调如果用了普通 function,this 指向的是 Sortable 实例而不是你的组件/对象。如果你想用 this.myArray,要么在外层保存引用,要么用箭头函数:
你可以先打印一下 oldIndex 和 newIndex 看看具体是多少,再打印 myArray 看看每一步的变化,这样能定位到底是哪一步出的问题。
正确做法是判断一下索引关系: