最近需要实现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-column
v-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: "2016-05-03",
name: "A",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-02",
name: "B",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-04",
name: "C",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-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>
在这里感谢 ty6693 用户提出的问题,因为实际项目中并没有用到,所以写完了就一直没有再看。
表头为啥会变,是因为拖拽的过程sortablejs
改变了表头的dom。sortablejs
只是改变了拖拽的元素,而table内容会变是因为我们在拖拽的时候改变了属性列的属性。