借助了插件sortablejs。这种方法只适合做非树状table。如果想实现树状table,并且可拖动。可以试一下aggridVue3这个插件
- <div class="draggable" style="padding: 20px">
- <el-table row-key="id" :data="tableData" style="width: 100%">
- <el-table-column v-for="(item, index) in oldList" :key="`col_${index}`" :prop="newList[index].prop"
- :label="item.label" align="center">
- el-table-column>
- el-table>
- div>
-
- <script setup lang="ts">
- import Sortable from 'sortablejs'
- import { onMounted, ref } from 'vue'
-
- // 只适合做平级的table行和列拖动
-
- const oldList = ref()
- const newList = ref()
-
- // 表头
- const tableItems = ref([
- {
- label: '姓名',
- prop: 'name',
- },
- {
- label: '性别',
- prop: 'gender',
- },
- {
- label: '年龄',
- prop: 'age',
- },
- ])
-
- // 表体数据
- const tableData = ref(
- [
- {
- id: 1,
- name: '李四',
- gender: '男',
- age: 20,
- },
- {
- id: 2,
- name: '王五',
- gender: '未知',
- age: 18,
- },
- {
- id: 3,
- name: '张三',
- gender: '男',
- age: 22,
- },
- ]
- )
-
- // 行拖拽
- const rowDrop = function () {
- // 要拖拽元素的父容器 tbody
- const tbody = document.querySelector('.draggable .el-table__body-wrapper tbody')
- Sortable.create(tbody, {
- // 可被拖拽的子元素
- draggable: ".draggable .el-table__row",
- onEnd({ newIndex, oldIndex }) {
- // newIndex 拖动到的新的索引
- // oldIndex 没拖动前的索引
- const currRow = tableData.value.splice(oldIndex, 1)[0]
- tableData.value.splice(newIndex, 0, currRow)
- }
- });
- }
-
- // 列拖拽
- const columnDrop = function () {
- // 要拖拽元素的父容器 头部的tr
- const wrapperTr = document.querySelector('.draggable .el-table__header-wrapper tr');
- Sortable.create(wrapperTr, {
- animation: 180,
- delay: 0,
- onEnd: (evt: any) => {
- const oldItem = newList.value[evt.oldIndex];
- newList.value.splice(evt.oldIndex, 1);
- newList.value.splice(evt.newIndex, 0, oldItem);
- }
- })
- }
-
- onMounted(() => {
- oldList.value = JSON.parse(JSON.stringify(tableItems.value))
- newList.value = JSON.parse(JSON.stringify(tableItems.value))
- columnDrop()
- rowDrop()
- })
- script>
效果如下
我试了加操作列,通过el-table-column的默认插槽进行实现,但是列拖动的时候,操作列的内容一直在最后一列,并没有跟着移动
代码如下,如果不需要列拖动的话,可以采取这种方式
- <div class="draggable" style="padding: 20px">
- <el-table row-key="id" :data="tableData" style="width: 100%">
- <el-table-column v-for="(item, index) in oldList" :key="`col_${index}`"
- :label="item.label" align="center">
- <template #default="{ row, column, $index }">
- <div v-if="column.label !== '操作'">
- {{ row[newList[index].prop] }}
- div>
- <div v-else>
- <el-button size="small">操作el-button>
- div>
- template>
- el-table-column>
- el-table>
- div>
-
- <script setup lang="ts">
- import Sortable from 'sortablejs'
- import { onMounted, ref } from 'vue'
-
- // 只适合做平级的table行和列拖动
-
- const oldList = ref()
- const newList = ref()
-
- // 表头
- const tableItems = ref([
- {
- label: '姓名',
- prop: 'name',
- },
- {
- label: '性别',
- prop: 'gender',
- },
- {
- label: '年龄',
- prop: 'age',
- },
- {
- label: '操作',
- prop: 'operate',
- },
- ])
-
- // 表体数据
- const tableData = ref(
- [
- {
- id: 1,
- name: '李四',
- gender: '男',
- age: 20,
- },
- {
- id: 2,
- name: '王五',
- gender: '未知',
- age: 18,
- },
- {
- id: 3,
- name: '张三',
- gender: '男',
- age: 22,
- },
- ]
- )
-
- // 行拖拽
- const rowDrop = function () {
- // 要拖拽元素的父容器 tbody
- const tbody = document.querySelector('.draggable .el-table__body-wrapper tbody')
- Sortable.create(tbody, {
- // 可被拖拽的子元素
- draggable: ".draggable .el-table__row",
- onEnd({ newIndex, oldIndex }) {
- // newIndex 拖动到的新的索引
- // oldIndex 没拖动前的索引
- const currRow = tableData.value.splice(oldIndex, 1)[0]
- tableData.value.splice(newIndex, 0, currRow)
- }
- });
- }
-
- // 列拖拽
- const columnDrop = function () {
- // 要拖拽元素的父容器 头部的tr
- const wrapperTr = document.querySelector('.draggable .el-table__header-wrapper tr');
- Sortable.create(wrapperTr, {
- animation: 180,
- delay: 0,
- onEnd: (evt: any) => {
- const oldItem = newList.value[evt.oldIndex];
- newList.value.splice(evt.oldIndex, 1);
- newList.value.splice(evt.newIndex, 0, oldItem);
- }
- })
- }
-
- onMounted(() => {
- oldList.value = JSON.parse(JSON.stringify(tableItems.value))
- newList.value = JSON.parse(JSON.stringify(tableItems.value))
- columnDrop()
- rowDrop()
- })
- script>
还有一种解决办法就是,把操作放到弹窗操作,比如双击某一行的时候,弹出弹窗,传入这行的数据,在弹窗里面进行操作,这样就不需要添加操作内一列了。行拖动和列拖动也都能使用