vue结合el-table实现表格行拖拽排序(基于sortablejs)

1. 实现效果

请添加图片描述

2. 安装 sortablejs 插件

sortablejs 更多用法

cnpm i --save sortablejs

3. 完整组件代码

<template>
  <div class="home">
    <div class="body">
      <el-table :data="tableData" border row-key="date" class="draggable-table" style="width: 100%">
        <el-table-column prop="sortNo" label="序号">
          <template slot-scope="{ row }">
            <img
              class="handle"
              :src="require('./icon-drop.png')"
              style="width: 20px; height: 20px; object-fit: contain"
            />
          </template>
        </el-table-column>
        <el-table-column prop="date" label="日期"></el-table-column>
        <el-table-column prop="name" label="姓名"></el-table-column>
        <el-table-column prop="address" label="地址"></el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
  import Sortable from 'sortablejs'
  export default {
    name: 'Demo',
    data() {
      return {
        tableData: [
          // 略去数据,与前段代码一直
          { date: '2024-01-02', name: '张三1', address: '深圳市' },
          { date: '2024-01-03', name: '李四2', address: '成都市' },
          { date: '2024-01-04', name: '王五3', address: '重庆市' },
          { date: '2024-01-05', name: '麻六4', address: '上海市' },
          { date: '2024-01-07', name: 'kk5', address: '上海市01' },
          { date: '2024-01-08', name: 'fantay6', address: '上海市02' },
        ],
      }
    },
    mounted() {
      const tbody = document.querySelector('.draggable-table .el-table__body-wrapper tbody')
      new Sortable(tbody, {
        handle: '.handle', // handle's class
        animation: 150,
        // 需要在odEnd方法中处理原始eltable数据,使原始数据与显示数据保持顺序一致
        onEnd: ({ newIndex, oldIndex }) => {
          const targetRow = this.tableData[oldIndex]
          this.tableData.splice(oldIndex, 1)
          this.tableData.splice(newIndex, 0, targetRow)
          console.table(this.tableData)
        },
      })
    },
  }
</script>

<style scoped lang="scss">
  .home {
    .body {
      width: 890px;
      height: 500px;
      border: #ff3366 solid 10px;
      box-sizing: border-box;
      padding: 20px;
      box-sizing: border-box;
    }
  }
  .handle {
    cursor: move;
    display: flex;
    align-content: center;
  }
</style>


4. 注意点

  1. 很多文章使用 Sortable.create 但是我这样用没生效,使用 new Sortable 就行了
  2. 页面table添加类 draggable-table
  3. handle 可以配置可拖拽的指定元素,默认是当前行触发
  • 19
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
实现el-table拖拽排序,可以使用Vue3的拖拽指令`v-drag`。具体步骤如下: 1. 在el-table的每一上添加`v-drag`指令: ```html <el-table> <el-table-column label="序号" type="index"></el-table-column> <el-table-column label="名称" prop="name"></el-table-column> <el-table-column label="操作"> <template slot-scope="scope"> <el-button @click="deleteRow(scope.$index)">删除</el-button> </template> </el-table-column> <el-table-column label="排序"> <template slot-scope="scope"> <span>{{ scope.$index + 1 }}</span> </template> </el-table-column> <el-table-column label="拖拽排序" width="80"> <template slot-scope="scope"> <div class="drag-handle" v-drag> <i class="el-icon-s-grid"></i> </div> </template> </el-table-column> </el-table> ``` 2. 在Vue3组件中定义`v-drag`指令: ```javascript import { DirectiveBinding } from 'vue'; interface DragData { el: HTMLElement; startX: number; startY: number; lastX: number; lastY: number; targetIndex: number; } const dragData: DragData = { el: null, startX: 0, startY: 0, lastX: 0, lastY: 0, targetIndex: 0, }; function handleDragStart(event: MouseEvent) { const target = event.target as HTMLElement; const tableRow = target.closest('.el-table__row'); if (tableRow) { dragData.el = tableRow; dragData.startX = event.clientX; dragData.startY = event.clientY; dragData.lastX = event.clientX; dragData.lastY = event.clientY; dragData.targetIndex = parseInt(tableRow.dataset.index); tableRow.style.opacity = '0.5'; } } function handleDragEnd() { if (dragData.el) { dragData.el.style.opacity = '1'; dragData.el = null; } } function handleDrag(event: MouseEvent) { if (dragData.el) { const deltaX = event.clientX - dragData.lastX; const deltaY = event.clientY - dragData.lastY; dragData.el.style.transform = `translate(${deltaX}px, ${deltaY}px)`; dragData.lastX = event.clientX; dragData.lastY = event.clientY; } } function handleDrop(event: MouseEvent) { if (dragData.el) { const target = event.target as HTMLElement; const tableRow = target.closest('.el-table__row'); if (tableRow) { const targetIndex = parseInt(tableRow.dataset.index); if (targetIndex !== dragData.targetIndex) { const tableBody = dragData.el.closest('.el-table__body-wrapper'); const tableRows = Array.from(tableBody.querySelectorAll('.el-table__row')); const dragIndex = tableRows.indexOf(dragData.el); const removed = tableRows.splice(dragIndex, 1); tableRows.splice(targetIndex < dragIndex ? targetIndex : targetIndex - 1, 0, removed[0]); tableRows.forEach((row, index) => { row.dataset.index = index.toString(); row.style.transform = ''; }); } } handleDragEnd(); } } export default { mounted(el: HTMLElement, binding: DirectiveBinding) { el.addEventListener('mousedown', handleDragStart); document.addEventListener('mouseup', handleDrop); document.addEventListener('mousemove', handleDrag); }, unmounted() { document.removeEventListener('mouseup', handleDrop); document.removeEventListener('mousemove', handleDrag); }, }; ``` 3. 在组件中引入`v-drag`指令,并绑定到el-table拖拽排序列上: ```javascript <template> <el-table> <el-table-column label="序号" type="index"></el-table-column> <el-table-column label="名称" prop="name"></el-table-column> <el-table-column label="操作"> <template slot-scope="scope"> <el-button @click="deleteRow(scope.$index)">删除</el-button> </template> </el-table-column> <el-table-column label="排序"> <template slot-scope="scope"> <span>{{ scope.$index + 1 }}</span> </template> </el-table-column> <el-table-column label="拖拽排序" width="80"> <template slot-scope="scope"> <div class="drag-handle" v-drag> <i class="el-icon-s-grid"></i> </div> </template> </el-table-column> </el-table> </template> <script> import vDrag from './v-drag'; export default { directives: { drag: vDrag, }, methods: { deleteRow(index) { // ... }, }, }; </script> ``` 4. 完成后,就可以实现el-table拖拽排序了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

范特西是只猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值