vue3 element plus table+Sortable.js 行拖动,表格拖动 电脑版发表于:2021/3/23 16:23 要先安装好Sortable.js依赖 ``` cnpm install sortable.js ``` ### 实现拖动的代码如下 可以直接复制运行 ``` <template> <div class="app-container"> <el-card> <el-table :data="state.tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </el-card> </div> </template> <script lang="ts" setup> import { defineAsyncComponent, reactive, toRefs, onMounted, ref } from 'vue' import Sortable from 'sortablejs' const state = reactive({ tableData: [ { date: '2016-05-03', name: 'Tom-1', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom-2', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom-3', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-01', name: 'Tom-4', address: 'No. 189, Grove St, Los Angeles', }, ] }) //行拖拽 const dragSort = () => { let that = this; // 首先获取需要拖拽的dom节点 const el1 = document.querySelectorAll('.el-table__body-wrapper')[0].querySelectorAll('table > tbody')[0]; Sortable.create(el1, { disabled: false, // 是否开启拖拽,false为开启 ghostClass: 'sortable-ghost', //拖拽样式 animation: 150, // 拖拽延时,效果更好看 group: { // 是否开启跨表拖拽 pull: false, put: false }, onEnd: (evt: any) => { //进行数据的处理,拖拽实际并不会改变绑定数据的顺序 console.log("拖动结束了,", evt) // 可以获取拖动前与拖动后的序号 const { newIndex, oldIndex } = evt console.log(oldIndex, newIndex) // 数据源不会变的哦 console.log(state.tableData) } }); } onMounted(() => { // 实现行拖拽。这个方法一般都要放到数据回来之后,比如数据是通过接口回来的 dragSort() }) </script> <style scoped="scoped" lang="scss"> </style> ``` ### 进行绑定的数据源处理,拖拽实际并不会改变绑定数据的顺序 一般存储改造后的数据就可以了,调用存储方法存储一下就行了。这里要特别注意`el-table的row-id属性这个必需要添加,否则进行数据源操作后数据顺序会错乱哦` ``` <template> <div class="app-container"> <el-card> <el-table :data="state.tableData" row-key="id" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </el-card> </div> </template> <script lang="ts" setup> import { defineAsyncComponent, reactive, toRefs, onMounted, ref } from 'vue' import Sortable from 'sortablejs' const state = reactive({ dictTableKey:1, tableData: [ { id:"1", date: '2016-05-03', name: 'Tom-1', address: 'No. 189, Grove St, Los Angeles', }, { id:"2", date: '2016-05-02', name: 'Tom-2', address: 'No. 189, Grove St, Los Angeles', }, { id:"3", date: '2016-05-04', name: 'Tom-3', address: 'No. 189, Grove St, Los Angeles', }, { id:"4", date: '2016-05-01', name: 'Tom-4', address: 'No. 189, Grove St, Los Angeles', }, ] }) //行拖拽 const dragSort = () => { let that = this; // 首先获取需要拖拽的dom节点 const el1 = document.querySelectorAll('.el-table__body-wrapper')[0].querySelectorAll('table > tbody')[0]; Sortable.create(el1, { disabled: false, // 是否开启拖拽,false为开启 ghostClass: 'sortable-ghost', //拖拽样式 animation: 150, // 拖拽延时,效果更好看 group: { // 是否开启跨表拖拽 pull: false, put: false }, onEnd: (evt: any) => { //进行数据的处理,拖拽实际并不会改变绑定数据的顺序 console.log("拖动结束了,", evt) // 可以获取拖动前与拖动后的序号 const { newIndex, oldIndex } = evt console.log(oldIndex, newIndex) // 数据源不会变的哦 console.log("改造前的数据源", state.tableData) // 这样可以把拖动前的那一行取出来 // const currRow = state.tableData[oldIndex] // 把拖动前的那一行干掉并且取出来 const currRow = state.tableData?.splice(oldIndex, 1)[0] // 把拖动前的那一行放到拖动后的位置 state.tableData?.splice(newIndex, 0, currRow) // 一般存储改造后的数据就可以了,调用存储方法存储一下就行了。 } }); } onMounted(() => { // 实现行拖拽。这个方法一般都要放到数据回来之后,比如数据是通过接口回来的 dragSort() }) </script> <style scoped="scoped" lang="scss"></style> ``` **如果不想改变数据源,可以复制一份数据源出来改造:** 当然这种情况还是比较少的,一般都直接操作数据源了,存储也好存储,不然可能还要维护多份数据 ``` onEnd: (evt: any) => { //进行数据的处理,拖拽实际并不会改变绑定数据的顺序 console.log("拖动结束了,", evt) // 可以获取拖动前与拖动后的序号 const { newIndex, oldIndex } = evt console.log(oldIndex, newIndex) // 数据源不会变的哦 console.log("改造前的数据源",state.tableData) // 这样可以把拖动前的那一行取出来 // const currRow = state.tableData[oldIndex] // 复制一份数据出来改造 let copyData = JSON.parse(JSON.stringify(state.tableData)) // 把拖动前的那一行干掉并且取出来 const currRow = copyData?.splice(oldIndex, 1)[0] // 把拖动前的那一行放到拖动后的位置 copyData?.splice(newIndex, 0, currRow) console.log("改造后的数据源",copyData) // 一般用保存后的数据,调用存储方法存储一下就行了 //state.tableData = copyData } ``` ### dom节点可以通过vue3的ref来获取,特别是封装成组件后每个组件里边的表格都需要拖动的情况 ``` <div ref="tableDataWrappeRef"> <el-card> <el-table :data="state.tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </el-card> </div> ``` ts部分: ``` // dom节点可以通过vue3的ref来获取,特别是封装成组件后每个组件里边的表格都需要拖动的 const el1 = tableDataWrappeRef.value.querySelectorAll('.el-table__body-wrapper')[0].querySelectorAll('table > tbody')[0]; ``` **注意ref要放到dom对象上面比如div,不要放到组件上面,也就是不要放到el-table上面,比如不要这么写:** 这样放到组件上面获取不到dom节点哦 ``` <el-card ref="tableDataWrappeRef"> <el-table :data="state.tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </el-card> ```