Vue实现拖拽布局
Vue 实现拖拽布局的方法
使用 HTML5 原生拖拽 API
HTML5 提供了原生的拖拽 API,可以通过 draggable 属性、dragstart、dragend、dragover 和 drop 事件实现基础拖拽功能。
<template>
<div
v-for="(item, index) in items"
:key="index"
draggable="true"
@dragstart="handleDragStart(index, $event)"
@dragover.prevent
@drop="handleDrop(index, $event)"
>
{{ item }}
</div>
</template>
<script>
export default {
data() {
return {
items: ['Item 1', 'Item 2', 'Item 3'],
draggedIndex: null
};
},
methods: {
handleDragStart(index, event) {
this.draggedIndex = index;
event.dataTransfer.setData('text/plain', index);
},
handleDrop(index, event) {
const draggedIndex = this.draggedIndex;
if (draggedIndex !== null) {
const newItems = [...this.items];
const [removed] = newItems.splice(draggedIndex, 1);
newItems.splice(index, 0, removed);
this.items = newItems;
}
}
}
};
</script>
使用第三方库 Vue.Draggable
Vue.Draggable 是一个基于 Sortable.js 的 Vue 组件,提供了更简单的拖拽实现方式。
安装依赖:
npm install vuedraggable
示例代码:
<template>
<draggable v-model="items" @end="onDragEnd">
<div v-for="(item, index) in items" :key="index">
{{ item }}
</div>
</draggable>
</template>
<script>
import draggable from 'vuedraggable';
export default {
components: { draggable },
data() {
return {
items: ['Item 1', 'Item 2', 'Item 3']
};
},
methods: {
onDragEnd() {
console.log('拖拽完成', this.items);
}
}
};
</script>
实现网格拖拽布局
对于网格布局的拖拽,可以使用 vue-grid-layout 库。
安装依赖:
npm install vue-grid-layout
示例代码:
<template>
<grid-layout
:layout="layout"
:col-num="12"
:row-height="30"
@layout-updated="layoutUpdated"
>
<grid-item
v-for="item in layout"
:key="item.i"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
:i="item.i"
>
{{ item.i }}
</grid-item>
</grid-layout>
</template>
<script>
import { GridLayout, GridItem } from 'vue-grid-layout';
export default {
components: { GridLayout, GridItem },
data() {
return {
layout: [
{ x: 0, y: 0, w: 2, h: 2, i: '0' },
{ x: 2, y: 0, w: 2, h: 2, i: '1' },
{ x: 4, y: 0, w: 2, h: 2, i: '2' }
]
};
},
methods: {
layoutUpdated(newLayout) {
this.layout = newLayout;
}
}
};
</script>
自定义拖拽逻辑
如果需要更复杂的拖拽逻辑,可以结合 Vue 的响应式数据和事件系统实现自定义拖拽。
<template>
<div class="container">
<div
v-for="(item, index) in items"
:key="index"
class="draggable-item"
:style="{ left: item.x + 'px', top: item.y + 'px' }"
@mousedown="startDrag(index, $event)"
@mousemove="onDrag($event)"
@mouseup="stopDrag"
>
{{ item.text }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ text: 'Item 1', x: 0, y: 0 },
{ text: 'Item 2', x: 100, y: 0 },
{ text: 'Item 3', x: 200, y: 0 }
],
dragging: false,
currentIndex: null,
startX: 0,
startY: 0
};
},
methods: {
startDrag(index, event) {
this.dragging = true;
this.currentIndex = index;
this.startX = event.clientX - this.items[index].x;
this.startY = event.clientY - this.items[index].y;
},
onDrag(event) {
if (this.dragging) {
const newItems = [...this.items];
newItems[this.currentIndex].x = event.clientX - this.startX;
newItems[this.currentIndex].y = event.clientY - this.startY;
this.items = newItems;
}
},
stopDrag() {
this.dragging = false;
}
}
};
</script>
<style>
.container {
position: relative;
width: 100%;
height: 300px;
border: 1px solid #ccc;
}
.draggable-item {
position: absolute;
width: 100px;
height: 50px;
background: #eee;
border: 1px solid #999;
cursor: move;
}
</style>
以上方法可以根据需求选择适合的方案实现拖拽布局,从简单的列表拖拽到复杂的网格布局均可覆盖。







