ElementUI-Table 表格实现行拖拽效果

 更新时间:2025年10月09日 09:16:45   作者:宣晨光  
在Vue中实现表格拖拽功能,需引入依赖,配置ref、row-key及row-drag-end事件,使用mounted钩子和key、$nextTick/$set确保数据刷新,添加样式完成拖拽效果,本文介绍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');
      // 初始化Sortable
      this.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,   // 拖拽行的ID
          originalIndex: 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 => {
        // 确保响应数据不为null
        this.tableData= response.rows ? response.rows : [];
        this.total = response.total ? response.total : 0;
      }).catch(error => {
        // 添加错误处理,防止数据为null
        console.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>

5、拖拽效果

到此这篇关于ElementUI-Table 表格实现行拖拽效果的文章就介绍到这了,更多相关ElementUI-Table 行拖拽内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 利用Vue实现移动端图片轮播组件的方法实例

    利用Vue实现移动端图片轮播组件的方法实例

    轮播图是前端很常用的一个网页特效,几乎所有的网站或多或少都会用到这个特效。下面这篇文章主要给大家介绍了关于利用Vue实现移动端图片轮播组件的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2017-08-08
  • vue中的插槽详解

    vue中的插槽详解

    这篇文章主要介绍了Vue中的插槽,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-10-10
  • vue3.0+vue-router+element-plus初实践

    vue3.0+vue-router+element-plus初实践

    这篇文章主要介绍了vue3.0+vue-router+element-plus初实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • iview在vue-cli3如何按需加载的方法

    iview在vue-cli3如何按需加载的方法

    这篇文章主要介绍了iview在vue-cli3如何按需加载的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • 详解vue mixins和extends的巧妙用法

    详解vue mixins和extends的巧妙用法

    vue提供了mixins、extends配置项,最近使用中发现很好用。下面小编通过本文给大家介绍下vue中 mixins和extends的巧妙用法,需要的朋友参考下吧
    2017-12-12
  • 使用Vue3和Echarts 5绘制带有立体感流线中国地图(推荐收藏!)

    使用Vue3和Echarts 5绘制带有立体感流线中国地图(推荐收藏!)

    最近接到一个需求是做一个中国地图,下面这篇文章主要给大家介绍了关于如何使用Vue3和Echarts 5绘制带有立体感流线中国地图的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-04-04
  • vue中对token有效期的深入理解

    vue中对token有效期的深入理解

    本文主要介绍了vue中对token有效期的深入理解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • 简单的vuex 的使用案例笔记

    简单的vuex 的使用案例笔记

    这篇文章主要介绍了简单的vuex 的使用案例笔记,本文通过demo 是一个 改变 app 的模式 的一个appellation ,选择是 夜间模式还是白天模式,具体代码大家参考下本文
    2018-04-04
  • vue自定义插件封装,实现简易的elementUi的Message和MessageBox的示例

    vue自定义插件封装,实现简易的elementUi的Message和MessageBox的示例

    这篇文章主要介绍了vue自定义插件封装,实现简易的elementUi的Message和MessageBox的示例,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下
    2020-11-11
  • vuejs中监听窗口关闭和窗口刷新事件的方法

    vuejs中监听窗口关闭和窗口刷新事件的方法

    今天小编就为大家分享一篇vuejs中监听窗口关闭和窗口刷新事件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09

最新评论