前言
最近需要实现table表格,行拖拽的功能,参照了一些优秀文章,实现了一下
参考文章
Vue进阶(幺零五):elementUI 实现表格行列拖拽
实现思路
主要是借助sortablejs
,关于sortablejs
我简单写了篇文章,有兴趣的可以看一下
拖拽,draggable组件和sortablejs
安装
npm install draggable
需要注意的是element table务必指定row-key,且row-key必须是唯一的,如ID,不然会出现排序不对的情况。
实现思路
1、定义一个列的数组,用来放列的数据。然后循环将列渲染出来
2、定义一个拖拽列的数组,拖拽后改变列在数组中的排列顺序
代码
<template><div><el-table :data="tableData" row-key="id" border style="width: 50%"><el-table-column type="index" label="序号" width="100" align="center" /><el-table-columnv-for="(item, index) in colList"align="center"show-overflow-tooltip:key="`col_${index}`":prop="dropCol[index].prop":label="item.label":min-width="item.minWidth"><template v-slot="scope"><span v-if="dropCol[index].prop == 'date'" style="color: blue">{{scope.row[dropCol[index].prop] }}</span><span v-else>{{scope.row[dropCol[index].prop] }}</span></template></el-table-column></el-table><pre style="text-align: left">{{dropCol }}</pre><hr /><pre style="text-align: left">{{tableData }}</pre></div></template><script>import Sortable from "sortablejs";import colDrap from "./drag";export default {data() {return {//动态列数组colList: [{label: "日期",prop: "date",minWidth: 100,},{label: "姓名",prop: "name",minWidth: 200,},{label: "地址",prop: "address",minWidth: 300,},],//拖拽列dropCol: [{label: "日期",prop: "date",minWidth: 100,},{label: "姓名",prop: "name",minWidth: 200,},{label: "地址",prop: "address",minWidth: 300,},],tableData: [{date: "-05-03",name: "A",address: "No. 189, Grove St, Los Angeles",},{date: "-05-02",name: "B",address: "No. 189, Grove St, Los Angeles",},{date: "-05-04",name: "C",address: "No. 189, Grove St, Los Angeles",},{date: "-05-01",name: "D",address: "No. 189, Grove St, Los Angeles",},],};},mounted() {this.dropCol = colDrap(this.dropCol);},methods: {},};</script><style scoped lang="scss"></style>
import Sortable from "sortablejs";//列拖拽function columnDrop(dropCol) {//获取dom节点const wrapperTr = document.querySelector(".el-table__header-wrapper tr");Sortable.create(wrapperTr, {animation: 180,delay: 0,onEnd: (evt) => {const oldItem = dropCol[evt.oldIndex - 1];dropCol.splice(evt.oldIndex - 1, 1);dropCol.splice(evt.newIndex - 1, 0, oldItem);},});return dropCol;}export default columnDrop;
关于插槽的使用,可以通过v-if
来判断
<template v-slot="scope"><span v-if="dropCol[index].prop == 'date'" style="color: blue">{{scope.row[dropCol[index].prop] }}</span><span v-else>{{scope.row[dropCol[index].prop] }}</span></template>
效果
关于表头label为啥会变的原因
在这里感谢ty6693用户提出的问题,因为实际项目中并没有用到,所以写完了就一直没有再看。
表头为啥会变,是因为拖拽的过程sortablejs
改变了表头的dom。sortablejs
只是改变了拖拽的元素,而table内容会变是因为我们在拖拽的时候改变了属性列的属性。