vue 实现表格列拖动
实现表格列拖动的核心方法
使用 Vue 实现表格列拖动功能主要依赖 HTML5 的拖放 API 和 Vue 的数据绑定特性。以下是具体实现步骤:
基础拖放 API 设置
为表格列头添加 draggable 属性启用拖放:
<th
v-for="(col, index) in columns"
:key="col.key"
draggable="true"
@dragstart="handleDragStart($event, index)"
@dragover.prevent="handleDragOver($event, index)"
@drop="handleDrop($event, index)"
>
{{ col.title }}
</th>
拖放事件处理逻辑
在 Vue 组件中实现三个核心方法:
methods: {
handleDragStart(e, index) {
e.dataTransfer.setData('text/plain', index)
e.dataTransfer.effectAllowed = 'move'
},
handleDragOver(e, index) {
e.preventDefault()
e.dataTransfer.dropEffect = 'move'
},
handleDrop(e, index) {
const fromIndex = e.dataTransfer.getData('text/plain')
const toIndex = index
if (fromIndex !== toIndex) {
const newColumns = [...this.columns]
const [removed] = newColumns.splice(fromIndex, 1)
newColumns.splice(toIndex, 0, removed)
this.columns = newColumns
}
}
}
使用第三方库的优化方案
对于复杂场景,推荐使用 vuedraggable 库:
npm install vuedraggable
组件中使用方式:
<draggable
v-model="columns"
tag="tr"
item-key="key"
>
<template #item="{ element }">
<th>{{ element.title }}</th>
</template>
</draggable>
样式优化技巧
添加拖拽时的视觉反馈:
th[draggable] {
cursor: move;
user-select: none;
}
th.drag-over {
background-color: #f0f0f0;
border: 2px dashed #666;
}
在 Vue 方法中动态添加类名:
handleDragOver(e, index) {
e.preventDefault()
e.target.classList.add('drag-over')
},
handleDragLeave(e) {
e.target.classList.remove('drag-over')
}
性能优化建议
对于大型表格,使用虚拟滚动技术:
<virtual-scroller
:items="data"
:item-height="50"
>
<template #default="{ item }">
<tr>
<td v-for="col in columns" :key="col.key">
{{ item[col.key] }}
</td>
</tr>
</template>
</virtual-scroller>
兼容性处理方案
为不支持 HTML5 拖放的浏览器提供降级方案:
if (!('draggable' in document.createElement('th'))) {
this.$refs.table.addEventListener('mousedown', this.handleMouseDrag)
}
实现鼠标拖拽的替代逻辑:
handleMouseDrag(e) {
if (e.target.tagName !== 'TH') return
const th = e.target
const startX = e.clientX
const startIndex = [...th.parentNode.children].indexOf(th)
const moveHandler = (moveEvent) => {
const currentX = moveEvent.clientX
// 计算拖动位置逻辑
}
document.addEventListener('mousemove', moveHandler)
document.addEventListener('mouseup', () => {
document.removeEventListener('mousemove', moveHandler)
}, { once: true })
}






