拖拽表格行时数据和视图不同步怎么办?
我用原生 JS 实现了表格行的拖拽排序,但拖完之后页面上看起来顺序对了,实际数据数组没变,点保存还是老顺序,这咋整?
试过在 drop 事件里手动 splice 调整数组,但索引老是算错,特别是跨行拖动的时候。有没有靠谱的处理方式?
function handleDrop(e) {
const draggedIndex = parseInt(e.dataTransfer.getData('text/plain'));
const targetIndex = [...table.rows].indexOf(e.target.closest('tr'));
// 这里交换数组元素经常出错
const item = dataList[draggedIndex];
dataList.splice(draggedIndex, 1);
dataList.splice(targetIndex, 0, item);
}
你想想,当你把第 0 行拖到第 3 行的位置,先执行
splice(0, 1)删除了元素,数组长度减 1,原来第 3 行的元素现在实际在第 2 行的位置。这时候你再用splice(3, 0, item)插入,位置就错了。正确的做法是根据拖拽方向来调整插入位置。往下拖的时候,目标索引要减 1;往上拖的时候直接用目标索引就行。
给你改了一版:
还有几个坑得提醒你。一个是
e.target可能是 td 或者 span 之类的子元素,必须用closest('tr')找到行元素,这块你倒是处理了。另一个是如果表格有 thead,table.rows会把表头也算进去,索引就对不上了,建议用querySelectorAll('tbody tr')只取数据行。最后别忘了在
dragover事件里e.preventDefault(),不然 drop 事件压根不会触发,这个低级错误我以前也踩过。