最近项目需要实现一个表单拖拽更换位置的功能,第一时间想到了sortablejs这个库,因为在以前的开发过程中简单的使用过一次,感觉不错,重点是不侵入组件,所以本次还是准备用它,不过开发过程中却是遇到了很多问题。
关于该库如何使用这里就不过多赘述了,可以直接看中文文档,已经介绍的很清楚了Sortable.js中文网|配置
一、是否可以在长列表进行滚动拖拽?
该问题是因为本次列表选用的是一个长列表,虽然数据量不会特别大,但是也会超出一屏,所以一定会涉及到滚动。通过查看API发现是可以支持滚动的,通过配置项中设置scroll:el(table元素) 即可实现在表单中滚动。
new Sortable(tbody as any, {
scroll: table as any,
bubbleScroll: true,
});
不过该情况也只是能进行滚动而已,必要条件是拖着元素到表格的头部和尾部才能进行滚动,其他地方无法进行。
二、onEnd方法无法实时获取表单值?
onEnd方法是拖拽后的回调方法,通常需要在这里面处理一些请求,包括把排序后的值传递给后端、更新数据等,但是操作后发现onEnd方法是无法实时获取表格数据的,拿到的只是创建时的瞬时值,解决办法就是将Sortable对象存储起来,每次更新的时候进行销毁 Sortable.destroy()
const sortable = useRef<Sortable>()
const [dataSource,setDataSource] = useState<any[]>([])
const onRowDrop = useCallback(()=>{
if(sortable.current){
sortable.current.destroy()
}
sortable.current = new Sortable(tbody as any, {
scroll: table as any,
bubbleScroll: true,
animation: 200,
ghostClass: 'blue-background-class',
touchStartThreshold: 3,
onEnd: ({ newIndex, oldIndex }: any) => {
const list = [...dataSource]
const curRow = list.splice(oldIndex, 1)[0];
list.splice(newIndex, 0, curRow);
//doSomething
});
}
});
},[dataSource])
三、拖拽后出现回跳问题
这个问题很坑,因为所有的操作都是正确,返回值也是正确的,包括onEnd里面执行的操作也都成功了,数据源也更改了,但是就是拖拽完成后会回跳,刷新页面后排序也是拖拽后的顺序,就很蛋疼,找了很久才发现。
先整理一下现象: 1、拖拽数据正常 2、拖拽结束后会回到原处
问题的根源是DOM节点和Virtual DOM不一致导致的,Sortabled不会侵入你的组件,它会直接对真实的DOM进行修改,所以当我们直接拖拽后真实DOM发生改变,但是页面更新后触发patch,会发现当前值和原值并未发生改变,所以会变回原来状态,导致发生回跳现象。
解决办法:给table每行都加key
<Table rowKey='id' {...props}>