AntDesign table 使用 Sortablejs实现拖拽采坑

2,268 阅读2分钟

最近项目需要实现一个表单拖拽更换位置的功能,第一时间想到了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}>