前端可拖动排序

前端列表样式的可拖动排序

image-20240822090004682

1.步骤,前端正常写表格,并且存放字段

2.在vue生命周期函数mounted中调用初始化拖动调整顺序的方法

操作 DOM 元素:因为在 mounted() 调用时,组件的 DOM 结构已经被渲染出来,

​ 所有 DOM 元素都是可访问的。这时候可以安全地操作 DOM 元素。

初始化第三方库:像 SortableJS 这样的第三方库,通常依赖于存在的 DOM 元素来进行操作,

​ 因此需要在 DOM 渲染完成后进行初始化。

1
2
3
4
mounted() {
// 初始化
this.initSort()
},

3.method里定义初始化排序方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
initSort() {
//用于获取页面中所有符合指定选择器的元素的函数,这里查找的是表格的<tbody>部分。
//选择第一个元素,el应该是一个dom元素,而不是一个值
const el = document.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
console.log(el);
//使用了 SortableJS 库,它是一个开源的库,用于实现可拖动排序的功能。
const sortable = new Sortable(el, {
//这是 SortableJS 的一个回调函数,当拖拽操作结束时触发。
//evt.oldIndex 和 evt.newIndex 分别表示拖动前后元素的索引位置。
onEnd: evt => {
//移除被拖动的行。删除从oldIndex开始的第1行,返回被删除的第一个元素(唯一一个)
const curRow = this.projectPhaseInputList.splice(evt.oldIndex, 1)[0]
//将移除的行插入到新位置。0表示不删除任何元素,curRow表示要插入元素
this.projectPhaseInputList.splice(evt.newIndex, 0, curRow);
//拖拽排序完成后对数据进行进一步处理
this.adjustPhaseOrder();
}
})
}

4.拖拽完成排序后,对数据进行进一步处理,生成弹窗

确定:调整序号,保存

取消:放弃调整,重新获取列表数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
adjustPhaseOrder(){
this.$confirm('是否按该顺序调整?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//点击确定的时候,执行保存方法,保存调整后的顺序
this.saveAdjustPhaseOrderData();
}).catch(() => {
//点击取消的时候,放弃调整,重新获取列表数据
this.getProjectPhaseInputList();
});
},

//异步的方法:用于将调整后的阶段顺序保存到数据库中
async saveAdjustPhaseOrderData(){
//显示加载动画
this.tableLoading = true;
const promises = [];
//遍历调整序号,调整后调用api方法存入数据库中
for (let i = 1; i <= this.projectPhaseInputList.length; i++) {
if(i != this.projectPhaseInputList[i-1].phaseOrder){
this.projectPhaseInputList[i-1].phaseOrder = i;
promises.push(saveProjectPhaseInput(this.projectPhaseInputList[i-1]).then(response => {
}));
}
}
// 等待所有异步操作完成
await Promise.all(promises);
this.tableLoading = false;
}


//从后端获取当前项目阶段的输入列表,并更新
getProjectPhaseInputList() {
//开始加载动画
this.tableLoading = true;
//api方法,发送请求,获取阶段输入列表
getProjectPhaseInputByConfigId(this.projectTypeConfig.boProjectTypeConfigId)
.then(response => {
this.projectPhaseInputList = response;
this.tableLoading = false;
});
}

拖动可排序

同上,使用sortable的开源库,获取dom元素,

执行回调:移除被拖动的行,将移除的行插入到新的位置

再次执行,对拖拽完成的数据进一步处理

主要不同的地方是:dom元素的获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
initSort2(){
// const el1 = document.querySelectorAll('#tagInput > span');
// console.log("这是tags的el1元素长度"+el1.length);
// console.log("这是tags的el1元素"+el1);
const el2 = document.querySelectorAll('#tagInput')[0];
// console.log("这是tags的el2元素"+el2);

const sortable2 = new Sortable(el2, {
onEnd: evt => {
const curRow = this.projectPhaseInput.fileList.splice(evt.oldIndex, 1)[0]
this.projectPhaseInput.fileList.splice(evt.newIndex, 0, curRow);
console.log(this.projectPhaseInput.fileList);
}
})
},
1
2
3
4
//table
const el = document.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
//tag
const el2 = document.querySelectorAll('#tagInput')[0];

table查看信息中的dom元素

image-20240828092126695

tag查看信息中的dom元素

1
2
//tag
const el2 = document.querySelectorAll('#tagInput')[0];

这里就很奇怪,只有点击了添加附件类型才能生成dom元素tag

才能拿到,有点小bug

image-20240828092337075

解决bug方法

1
2
3
4
5
6
7
8
9
watch: {
'projectPhaseInput.fileList'(newVal, oldVal) {
if (newVal.length > 0) {
this.$nextTick(() => {
this.initSort2();
});
}
}
}

设置监听器,监听tag列表新值,和旧值的变化,

$nextTick 是 Vue.js 中的一个方法,用于在下一次 DOM 更新循环之后执行回调。这确保了 DOM 已经完成更新,然后再执行接下来的操作。

就可以拿到dom元素了

再执行初始化拖动就可以获取dom元素了