vue2实现列表横向拖拽排序(列数据、列表头对应更新)
所需的库
- sortablejs
- element ui
具体实现效果
用户可以通过拖动首行列表头控制整列的排列顺序,并且存入本地。
遇到的坑
通过v-for生成列表,key值选取问题(解决拖拽时列数据和表头对应不上的问题)
这个问题在csdn上有很多解决方案,但大多都失败了(比如key取index,path等),其余的即使可以实现,也会影响到我项目的其他模块(本人用的若依框架开发),这里直接说我现在key的获取:通过全局js文件给表头分配一个key,每当表头更新的时候通过全局方法手动修改key值,这样就能触发vue的diff算法重新渲染列表,全局js文件代码如下:
- tableData.js
//Mes表格数据
const tableData = {
prePartCol: [
{
label: '操作',
key: 0,
},
{
label: '预套料零件ID',
prop: 'id',
key: 1,
},
{
label: '零件编号',
prop: 'mat_code',
key: 2,
},
{
label: '预套料作业编码',
prop: 'preTaskCode',
key: 9,
},
{
label: '零件类型',
prop: 'iscircle',
key: 3,
},
{
label: '零件材质',
prop: 'mat_quality',
key: 4,
},
{
label: '零件长度/外径',
prop: 'length',
key: 5,
},
{
label: '零件宽度/内径',
prop: 'width',
key: 6,
},
{
label: '零件厚度',
prop: 'thick',
key: 7,
},
{
label: '数量',
prop: 'qty',
key: 8,
},
],
prePartList: [
{
label: '操作',
key: 0,
},
{
label: '预套料零件ID',
prop: 'id',
key: 1,
},
{
label: '零件编号',
prop: 'mat_code',
key: 2,
},
{
label: '零件类型',
prop: 'iscircle',
key: 3,
},
{
label: '零件材质',
prop: 'mat_quality',
key: 4,
},
{
label: '零件长度/外径',
prop: 'length',
key: 5,
},
{
label: '零件宽度/内径',
prop: 'width',
key: 6,
},
{
label: '零件厚度',
prop: 'thick',
key: 7,
},
{
label: '数量',
prop: 'qty',
key: 8,
},
{
label: '预套料作业编码',
prop: 'preTaskCode',
key: 9,
},
],
};
export default tableData;
这里仅列出一个表格所需的数据,其中prePartCol列表为表头的list,用于拖拽时改变的列,prePartList为原始list,用于储存列拖拽后的新list
- colDrag.js
import Sortable from "sortablejs";
// 列拖拽相关方法
export function columnDrop(dropCol) {
const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
Sortable.create(wrapperTr, {
animation: 180,
delay: 0,
ghostClass: 'sortable-ghost',
onEnd: (evt) => {
if(evt.newIndex == evt.oldIndex){
//这一句,是判断相同时不移动,也是解决,列宽拖动的问题
return dropCol;
}
const oldItem = dropCol[evt.oldIndex - 1]
dropCol.splice(evt.oldIndex - 1, 1)
dropCol.splice(evt.newIndex - 1, 0, oldItem)
}
})
return dropCol;
}
/** 判断表头是否更变顺序,若改变则修改对应的key值并更新原始数组 */
export function changeList(originalList, currentList){
for(let i = 0; i < originalList.length; i++){
if(originalList[i].key !== currentList[i].key){
currentList[i].key = currentList[i].key + 0.000000000000001;
originalList[i] = currentList[i];
}else{
// currentList[i].key = currentList[i].key - 0.000000000000001;
// originalList[i] = currentList[i];
}
}
}
export default columnDrop;
该全局方法通过引入sortablejs实现了列拖拽方法和表头key值手动更新方法,逻辑不难,参考sortablejs官方文档即可
页面实现
el-table
<el-table v-loading="loading" :data="partList" @selection-change="handleSelectionChange" @sort-change="sortChange">
<el-table-column type="selection" align="center" width="55" fixed="left" />
<el-table-column v-for="(item, index) in dropCol" align="center" show-overflow-tooltip :key="item.key"
:prop="dropCol[index].prop" :label="item.label" :min-width="item.minWidth" sortable="custom">
<template v-slot="scope">
<span v-if="dropCol[index].label === '操作'">
<router-link :to="{ name: 'Task', params: { showButton: false, preTaskCode: scope.row.preTaskCode } }"
class="link-type">
<span>{{ '查看预套料作业' }}</span>
</router-link>
</span>
<span v-if="dropCol[index].prop === 'iscircle'">
<dict-tag :options="dict.type.is_circle" :value="scope.row.iscircle" />
</span>
<span v-else>
{{ scope.row[dropCol[index].prop] }}
</span>
</template>
</el-table-column>
</el-table>
通过v-for渲染列表,partList数据绑定后端数据库,多选框列单独拎出来,用fixed="left"固定在左边,不然会影响列拖拽,dropCol为tableData.js中的prePartCol列表,列表中元素的顺序即为渲染出的默认顺序,若要对列表中某一属性做特殊处理可使用v-if选择
data
data() {
return {
// 预套料零件表格数据
partList: [],
dropCol: tableData.prePartCol,
originalList: tableData.prePartList,
},
mounted
mounted() {
this.dropCol = this.columnDrop(JSON.parse(localStorage.getItem('prePart'), 'prePart') || tableData.prePartCol);
this.getList();
console.log(this.dropCol);
},
通过localStorage或tableData获取dropCol,优先localStorage的方式
watch
watch: {
dropCol: function () {
//this.$forceUpdate()
console.log("我被触发了")
// console.log(this.dropCol.map(item => item.key))
// console.log(this.dropCol.map(item => item.label))
changeList(this.originalList, this.dropCol);
console.log(this.originalList.map(item => item.key))
localStorage.setItem('prePart', JSON.stringify(this.originalList));
},
监听dropCol的变化,发生变化就调用全局方法changeList(),实现key值的手动更新和originalList列表更新,然后在将新的列表存入localStorage
总结一下
通过上述方法基本可以实现大部分列表的列拖拽,嵌套列表没试过不确定,是否有更好地实现方法暂时还没有发现,如果有欢迎各位大佬评论留言,上述代码也存在很多不足,主要是为了满足客户需求hhh

浙公网安备 33010602011771号