element+Sortable 实现表格拖拽
<template>
<div :class="props.className" style="padding: 8px 0;">
<el-table :ref="props.refsName" row-key="id" :data="state.tableData" style="width: 100%" highlight-current-row
@current-change="handleCurrentClick">
<el-table-column label="序号" prop="serialNumber" width="65" align="center" />
<el-table-column type="expand" width="50" align="center">
<template #default="scope">
// 组件调用自己
<drag-table style="margin-left: 20px;" :className='className + "-" + scope.row.id'
:tableData="scope.row.children" :tableConfig="state.tableConfig"
v-if="scope.row.children && scope.row.children.length" @childrenChange="childrenClick"
:refsName="props.refsName + scope.row.id" :rowId="props.rowId" />
</template>
</el-table-column>
<el-table-column v-for="(item, index) in state.oldList" :key="`col_${index}`" :prop="state.newList[index].prop"
:label="item.label" align="center" />
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template #default="scope">
<el-button type="text" icon="Connection" @click="toDetail(scope.row)">编辑</el-button>
<el-button type="text" icon="Delete" @click="delById(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup name="DragTable">
import Sortable from 'sortablejs';
import { reactive, onMounted, watch, ref } from 'vue';
const { proxy } = getCurrentInstance();
const props = defineProps(['className', 'tableData', 'tableConfig', 'refsName', 'rowId'])
const emit = defineEmits(['childrenChange'])
const className = ref(props.className)
const state = ref({
oldList: [],
newList: [],
tableData: [],
tableConfig: []
})
const currentRow = ref(null) //用于记录被选中的行
const copyData = ref([])
watch(() => props.rowId, (val) => { console.log('rowId', val,currentRow.value) if(!currentRow.value) return if(!val&¤tRow.value) { proxy.$refs[props.refsName].setCurrentRow(-1) return } if (val !== currentRow.value.id) { proxy.$refs[props.refsName].setCurrentRow(-1) return } }) watch(() => props.tableData, (newVal) => { if (newVal && newVal.length) { state.value.tableData = newVal state.value.tableData.forEach(item => { item.children.forEach((its, index) => { its.serialNumber = item.serialNumber + '.' + (index + 1) }) })
copyData.value = props.tableData.map(item => item)
} }) // 行拖拽 const rowDrop = function (name) { // 要拖拽元素的父容器
// 寻找指定的class
const tbody = document.querySelector(`.${name} tbody`); Sortable.create(tbody, { // dragClass: "dragClass", //设置拖拽样式类名 ghostClass: "ghostClass", //设置拖拽停靠样式类名 // chosenClass: "chosenClass", //设置选中样式类名 // 可被拖拽的子元素 draggable: ".draggable .el-table__row", onEnd({ newDraggableIndex, oldDraggableIndex }) {
const currRow = copyData.value[oldDraggableIndex]
const nextItem = copyData.value[newDraggableIndex];
let type = ''
if (!currRow) return
let num = newDraggableIndex - oldDraggableIndex
if (num > 0) {
type = 'after'
console.log('after 在目标位置之后', nextItem)
} else if (num == 0) {
return
} else {
type = 'before'
console.log('brfore 在目标位置之前', nextItem)
}
copyData.value.splice(oldDraggableIndex, 1)
copyData.value.splice(newDraggableIndex, 0, currRow)
state.value.tableData = copyData.value
} }); } // 列拖拽 const columnDrop = function () { const wrapperTr = document.querySelector('.draggable .el-table__header-wrapper tr'); Sortable.create(wrapperTr, { animation: 180, delay: 0, onEnd: evt => { const oldItem = state.value.newList[evt.oldIndex]; state.value.newList.splice(evt.oldIndex, 1); state.value.newList.splice(evt.newIndex, 0, oldItem); } }); } // 行点击 const handleCurrentClick = (val) => { if(val == -1) return console.log('行点击', val) currentRow.value = val emit('childrenChange', val) } // 子表格行点击 const childrenClick = (data) => { console.log('子表格行点击', data) if(data == -1) return if(!currentRow.value) { emit('childrenChange', data) return } if(data.id !== currentRow.value.id) { proxy.$refs[props.refsName].setCurrentRow(-1) emit('childrenChange', data) return } } onMounted(() => { state.value.tableConfig = props.tableConfig state.value.oldList = props.tableConfig state.value.newList = props.tableConfig
state.value.tableData = props.tableData
copyData.value = props.tableData
columnDrop(props.className) rowDrop(props.className) }) </script> <style> /* .dragClass { background: #41c21a !important; } */ /* 停靠 */ .ghostClass { background: rgba(64, 158, 255, 0.2) !important; } /* 选择 */ /* .chosenClass:hover > td { background: #f56c6c !important; } */ </style>
示例数据:
const tableData = [{ date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }, { date: '2016-05-04', name: '王小虎', address: '上海市普陀区金沙江路 1517 弄' }, { date: '2016-05-01', name: '王小虎', address: '上海市普陀区金沙江路 1519 弄' }, { date: '2016-05-03', name: '王小虎', address: '上海市普陀区金沙江路 1516 弄' }]
const tableConfig = ref([ { label: '名称', prop: 'name', } ])

浙公网安备 33010602011771号