ElementUI-Table 表格实现行拖拽
1、引入依赖
npm install sortablejs --save
2、table表格设置
1、添加属性 ref="multipleTable" row-key="id" @row-drag-end="handleDragEnd"
2、添加列
<el-table-column width="50" align="center">
<template >
<i class="el-icon-rank drag-handle"></i>
</template>
</el-table-column>
<el-table v-loading="loading" :data="tableData" :highlight-selection-row="true" :key="componentKey"ref="multipleTable" row-key="id" @row-drag-end="handleDragEnd" ><el-table-column width="50" align="center"><template ><i class="el-icon-rank drag-handle"></i></template></el-table-column><el-table-column type="selection" width="55" align="center" /><el-table-column label="序号" type="index" align="center" min-width="5%" /></el-table>
显示效果如下
3、添加事件
1、必须是 mounted ,不可以使用created
2、解决无法二次拖拽、拖拽后表格数据无法重新渲染问题
补充: :
1、key="componentKey"
2、// 重新初始化拖拽功能
this.$nextTick(() => {
this.initDragAndDrop();
});3、 this.$set(this, 'materialList', newData);
<script>
import Sortable from "sortablejs";export default {name: "demo",data() {return {tableData: [], // 确保初始化为空数组sortable: null,componentKey: 1000,}},
created() {this.getList();},mounted() {this.initDragAndDrop();},methods: {initDragAndDrop() {// 获取表格的tbody元素const tbody = this.$refs.multipleTable.$el.querySelector('.el-table__body-wrapper tbody');// 初始化Sortablethis.sortable = new Sortable(tbody, {handle: '.drag-handle', // 指定拖拽手柄animation: 150, // 动画时间ghostClass: 'sortable-ghost', // 拖拽时的占位元素样式onEnd: (event) => {// 拖拽结束时触发this.handleDragEnd(event);}});console.log(this.sortable);},// 处理拖拽结束事件handleDragEnd(evt) {// 如果位置没有变化,不做处理if (evt.oldIndex === evt.newIndex) {return;}// 获取拖拽的行数据const draggingRow = this.materialList[evt.oldIndex];// 从原数组中移除并插入到新位置var newData = JSON.parse(JSON.stringify(this.materialList));;newData.splice(evt.newIndex, 0, newData.splice(evt.oldIndex, 1)[0]);console.log(newData)const nextRow = newData[evt.newIndex + 1];// 通知父组件数据已更新this.$set(this, 'materialList', newData);// 强制刷新组件以确保视图更新this.componentKey += 1;// 发送拖拽信息this.$emit('drag-end', {id: draggingRow.materialDeviceId, // 拖拽行的IDoriginalIndex: evt.oldIndex, // 原始位置(0开始)originalPosition: evt.oldIndex + 1, // 原始位置(1开始)newIndex: evt.newIndex, // 新位置(0开始)newPosition: evt.newIndex + 1, // 新位置(1开始)moved: evt.oldIndex !== evt.newIndex // 是否发生了移动});// TODO + -console.log(`拖拽完成 - ID: ${draggingRow.materialDeviceId}, 从第${evt.oldIndex + 1}行移到第${evt.newIndex + 1}行`);console.log('下一个位置:' , nextRow.materialDeviceId , nextRow.orderNum , nextRow.name)// 重新初始化拖拽功能this.$nextTick(() => {this.initDragAndDrop();});},/** 查询素材分配列表 */getList() {listDevice(this.queryParams).then(response => {// 确保响应数据不为nullthis.tableData= response.rows ? response.rows : [];this.total = response.total ? response.total : 0;}).catch(error => {// 添加错误处理,防止数据为nullconsole.error('获取数据失败:', error);this.tableData= [];this.total = 0;});},}} </script>
4、添加样式
<style scoped>
.el-icon-rank{
font-size: x-large;
}
/* 拖拽相关样式 */
.cursor-move {
cursor: move;
color: #909399;
transition: color 0.2s;
}.cursor-move:hover {
color: #409EFF;
}/* 拖拽时的占位符样式 */
::v-deep .sortable-ghost {
opacity: 0.5;
background-color: #f5f7fa;
}/* 选中行样式 */
::v-deep .sortable-chosen {
background-color: #e6f7ff !important;
}/* 正在拖拽的行样式 */
::v-deep .dragging-row {
background-color: #fffbe6 !important;
}
</style>