vue实现拖拽表格
Vue 拖拽表格实现方法
使用 vuedraggable 库
vuedraggable 是基于 Sortable.js 的 Vue 拖拽组件,适合表格行排序场景。
安装依赖:
npm install vuedraggable
基础实现代码:
<template>
<table>
<draggable v-model="tableData" tag="tbody" @end="onDragEnd">
<tr v-for="(item, index) in tableData" :key="item.id">
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
</tr>
</draggable>
</table>
</template>
<script>
import draggable from 'vuedraggable'
export default {
components: { draggable },
data() {
return {
tableData: [
{ id: 1, name: 'John', age: 25 },
{ id: 2, name: 'Jane', age: 30 }
]
}
},
methods: {
onDragEnd() {
console.log('新顺序:', this.tableData)
}
}
}
</script>
原生 HTML5 拖拽 API
通过原生拖拽事件实现更细粒度的控制。
<template>
<table>
<tbody>
<tr
v-for="(item, index) in tableData"
:key="item.id"
draggable="true"
@dragstart="handleDragStart(index)"
@dragover.prevent="handleDragOver(index)"
@drop="handleDrop(index)"
>
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
</tr>
</tbody>
</table>
</template>
<script>
export default {
data() {
return {
tableData: [...],
draggedIndex: null
}
},
methods: {
handleDragStart(index) {
this.draggedIndex = index
},
handleDragOver(index) {
if (this.draggedIndex !== index) {
const draggedItem = this.tableData[this.draggedIndex]
this.tableData.splice(this.draggedIndex, 1)
this.tableData.splice(index, 0, draggedItem)
this.draggedIndex = index
}
},
handleDrop() {
this.draggedIndex = null
}
}
}
</script>
表格列拖拽实现
实现表头列顺序拖拽需要单独处理 th 元素。
<template>
<table>
<thead>
<draggable
v-model="headers"
tag="tr"
@end="updateColumns"
>
<th v-for="header in headers" :key="header.key">
{{ header.text }}
</th>
</draggable>
</thead>
<tbody>
<tr v-for="item in tableData" :key="item.id">
<td v-for="header in headers" :key="header.key">
{{ item[header.key] }}
</td>
</tr>
</tbody>
</table>
</template>
性能优化建议
大数据量表格应使用虚拟滚动技术,结合拖拽时只更新必要 DOM 元素。

<template>
<div class="table-container" @scroll="handleScroll">
<table :style="{ height: totalHeight + 'px' }">
<tbody :style="{ transform: `translateY(${offsetY}px)` }">
<tr
v-for="item in visibleData"
:key="item.id"
draggable
@dragstart="handleDragStart(item.id)"
>
<td v-for="col in columns" :key="col.key">{{ item[col.key] }}</td>
</tr>
</tbody>
</table>
</div>
</template>
注意事项
- 移动端需添加 touch 事件支持
- 拖拽状态需要明确视觉反馈
- 复杂数据结构需深度监听变化
- 服务端持久化应在拖拽结束后统一提交
以上方案可根据实际需求组合使用,vuedraggable 适合快速实现,原生 API 适合定制化需求。表格列拖拽需要单独处理表头与数据列的映射关系。






