vue实现拖拽界面布局
Vue实现拖拽界面布局的方法
使用Vue.Draggable组件
Vue.Draggable是基于Sortable.js的Vue组件,适用于列表拖拽排序。安装依赖后,通过v-model绑定数据实现拖拽排序功能。
npm install vuedraggable
<template>
<draggable v-model="list" @end="onDragEnd">
<div v-for="item in list" :key="item.id">{{ item.name }}</div>
</draggable>
</template>
<script>
import draggable from 'vuedraggable'
export default {
components: { draggable },
data() {
return {
list: [{id:1,name:'A'}, {id:2,name:'B'}]
}
},
methods: {
onDragEnd() {
console.log('排序完成', this.list)
}
}
}
</script>
原生HTML5拖拽API
通过HTML5的draggable属性和拖拽事件实现基础拖拽功能。需要处理dragstart、dragover和drop事件。

<template>
<div
v-for="item in items"
:key="item.id"
draggable="true"
@dragstart="dragStart($event, item)"
@dragover.prevent
@drop="drop($event, item)"
>
{{ item.text }}
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ id: 1, text: 'Item 1' },
{ id: 2, text: 'Item 2' }
],
draggedItem: null
}
},
methods: {
dragStart(event, item) {
this.draggedItem = item
event.dataTransfer.effectAllowed = 'move'
},
drop(event, targetItem) {
const indexDragged = this.items.indexOf(this.draggedItem)
const indexTarget = this.items.indexOf(targetItem)
this.items.splice(indexDragged, 1)
this.items.splice(indexTarget, 0, this.draggedItem)
}
}
}
</script>
使用Grid布局拖拽
结合CSS Grid和拖拽API实现网格布局的拖拽功能。通过计算网格位置实现元素交换。

<template>
<div class="grid-container">
<div
v-for="item in gridItems"
:key="item.id"
class="grid-item"
draggable="true"
@dragstart="dragStart($event, item)"
@dragover.prevent
@drop="drop($event, item)"
>
{{ item.content }}
</div>
</div>
</template>
<style>
.grid-container {
display: grid;
grid-template-columns: repeat(3, 100px);
gap: 10px;
}
.grid-item {
border: 1px solid #ccc;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
}
</style>
使用第三方库interact.js
interact.js提供更丰富的拖拽功能,支持限制拖拽范围、吸附网格等高级特性。
npm install interactjs
<template>
<div ref="dragElement" class="draggable">拖拽我</div>
</template>
<script>
import interact from 'interactjs'
export default {
mounted() {
interact(this.$refs.dragElement)
.draggable({
inertia: true,
modifiers: [
interact.modifiers.restrictRect({
restriction: 'parent',
endOnly: true
})
],
onmove: this.dragMoveListener
})
},
methods: {
dragMoveListener(event) {
const target = event.target
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy
target.style.transform = `translate(${x}px, ${y}px)`
target.setAttribute('data-x', x)
target.setAttribute('data-y', y)
}
}
}
</script>
实现嵌套拖拽布局
通过组合Vue.Draggable的group属性实现嵌套结构的拖拽布局,支持跨容器拖拽。
<template>
<div class="container">
<draggable
v-model="columns"
group="sections"
@end="logChange"
class="columns-container"
>
<div v-for="(col, colIndex) in columns" :key="colIndex" class="column">
<draggable
v-model="col.items"
group="items"
@end="logChange"
>
<div v-for="item in col.items" :key="item.id" class="item">
{{ item.name }}
</div>
</draggable>
</div>
</draggable>
</div>
</template>
<script>
import draggable from 'vuedraggable'
export default {
components: { draggable },
data() {
return {
columns: [
{
items: [{id:1,name:'A1'}, {id:2,name:'A2'}]
},
{
items: [{id:3,name:'B1'}, {id:4,name:'B2'}]
}
]
}
},
methods: {
logChange() {
console.log('布局变更', this.columns)
}
}
}
</script>






