sortablejs实现element-ui表格可拖拽

75 阅读1分钟

引入依赖:

npm install sortablejs

行拖拽

<template>
  <div>
    <el-table :data="list" :border="true" ref="table" style="width: 50%">
      <el-table-column type="index" width="55" label="序号"/>
      <el-table-column prop="id" label="id" width="50"/>
      <el-table-column prop="name" label="名字"/>
      <el-table-column prop="sex" label="性别"/>
    </el-table>
    <hr>
  </div>
</template>

<script setup lang="ts">
import {ref, onMounted, nextTick} from 'vue'
import Sortable from "sortablejs";
import {SortableEvent} from 'sortablejs';

const list = ref([
  {
    sex: '男',
    name: 'name-1',
    id: 1
  },
  {
    sex: '女',
    name: 'name-2',
    id: 2
  },
  {
    sex: '男',
    name: 'name-3',
    id: 3
  },
  {
    sex: '女',
    name: 'name-4',
    id: 4
  }
])

const table = ref(null)

onMounted(() => {
  rowDraggable(table);
})


const rowDraggable = (table: any) => {
  const tableDom = table.value.$el.querySelector('.el-table__body-wrapper tbody')
  console.log(tableDom)
  Sortable.create(tableDom, {
    group: 'shared', //定义了拖拽组
    animation: 150, //设置动画持续时间为150毫秒
    ghostClass: 'sortable-ghost', //拖拽样式
    easing: 'cubic-bezier(1, 0, 0, 1)', //设置动画的缓动效果,这是一条线性缓动曲线
    // onStart: (event: SortableEvent) => {
    // },
    // 结束拖动事件
    onEnd: (event: SortableEvent) => {
      const {newIndex = 0, oldIndex = 0} = event
      const data = list.value
      const oldData = data.splice(oldIndex, 1)[0]
      data.splice(newIndex, 0, oldData)
      list.value = [];
      nextTick(() => {
        list.value = data;
      });
    },
  })
}

</script>

行列拖拽

<template>
  <div class="draggable" style="padding: 20px">
    <el-table row-key="id" :data="state.tableData" style="width: 100%">
      <el-table-column v-for="(item,index) in state.newList" :key="`col_${index}`" :prop="state.newList[index].prop" :label="item.label" align="center">
      </el-table-column>
    </el-table>
  </div>
</template>
<script setup>
import Sortable from 'sortablejs';
import { reactive, onMounted} from 'vue';
​
const state = reactive({
  newList: [],
  tableData: [
    {
      id:1,
      name:'李四',
      gender:'男',
      age:20,
    },
    {
      id:2,
      name:'王五',
      gender:'未知',
      age:18,
    },
    {
      id:3,
      name:'张三',
      gender:'男',
      age:22,
    },
    {
      id:4,
      name:'张大大',
      gender:'男',
      age:28,
    },
  ],
  tableConfig: {
    tableItems: [
      {
        label: 'id',
        prop: 'id',
      },
      {
        label: '姓名',
        prop: 'name',
      },
      {
        label: '性别',
        prop: 'gender',
      },
      {
        label: '年龄',
        prop: 'age',
      },
    ]
  }
​
})
// 行拖拽
const rowDrop = function () {
  // 要拖拽元素的父容器
  const tbody = document.querySelector('.draggable .el-table__body-wrapper tbody');
  Sortable.create(tbody, {
    //  可被拖拽的子元素
    draggable: ".draggable .el-table__row",
    onEnd({newIndex, oldIndex}) {
      const currRow = state.tableData.splice(oldIndex, 1)[0];
      state.tableData.splice(newIndex, 0, currRow);
    }
  });
}
// 列拖拽
const columnDrop = function() {
  const wrapperTr = document.querySelector('.draggable .el-table__header-wrapper tr');
  console.log(wrapperTr)
  Sortable.create(wrapperTr, {
    animation: 180,
    delay: 0,
    onEnd: evt => {
      const arr = state.newList
      const oldItem = arr.splice(evt.oldIndex, 1)[0];
      arr.splice(evt.newIndex, 0, oldItem);
      state.newList = []
      nextTick(()=>{
        state.newList = arr
      })
    }
  });
}
​
onMounted(()=> {
  state.newList = JSON.parse(JSON.stringify(state.tableConfig.tableItems))
  columnDrop()
  rowDrop()
})
</script>
​

注意:列拖拽不能有序号

<el-table-column type="index" width="55" label="序号"> </el-table-column>