vue3实现拖拽
vue3 拖拽实现方法
使用 HTML5 原生拖拽 API
HTML5 提供了原生拖拽 API,通过 draggable 属性、dragstart、dragend、dragover 和 drop 事件实现基础拖拽功能。
<template>
<div
draggable="true"
@dragstart="handleDragStart"
@dragend="handleDragEnd"
>可拖拽元素</div>
<div
@dragover.prevent
@drop="handleDrop"
>放置区域</div>
</template>
<script setup>
const handleDragStart = (e) => {
e.dataTransfer.setData('text/plain', '拖拽数据');
};
const handleDrop = (e) => {
const data = e.dataTransfer.getData('text/plain');
console.log('接收到的数据:', data);
};
</script>
使用第三方库 vue-draggable-next
对于更复杂的拖拽场景,推荐使用专门为 Vue 3 设计的拖拽库 vue-draggable-next。
安装依赖:
npm install vue-draggable-next
基本用法:
<template>
<draggable
v-model="list"
@end="onDragEnd"
item-key="id"
>
<template #item="{ element }">
<div>{{ element.name }}</div>
</template>
</draggable>
</template>
<script setup>
import { ref } from 'vue';
import draggable from 'vue-draggable-next';
const list = ref([
{ id: 1, name: '项目1' },
{ id: 2, name: '项目2' }
]);
const onDragEnd = () => {
console.log('排序后的列表:', list.value);
};
</script>
自定义拖拽实现
对于需要完全自定义的拖拽行为,可以通过组合式 API 实现。
<template>
<div
ref="dragElement"
@mousedown="startDrag"
:style="elementStyle"
>自定义拖拽元素</div>
</template>
<script setup>
import { ref } from 'vue';
const dragElement = ref(null);
const isDragging = ref(false);
const position = ref({ x: 0, y: 0 });
const startPos = ref({ x: 0, y: 0 });
const elementStyle = computed(() => ({
position: 'absolute',
left: `${position.value.x}px`,
top: `${position.value.y}px`,
cursor: isDragging.value ? 'grabbing' : 'grab'
}));
const startDrag = (e) => {
isDragging.value = true;
startPos.value = {
x: e.clientX - position.value.x,
y: e.clientY - position.value.y
};
window.addEventListener('mousemove', onDrag);
window.addEventListener('mouseup', stopDrag);
};
const onDrag = (e) => {
if (!isDragging.value) return;
position.value = {
x: e.clientX - startPos.value.x,
y: e.clientY - startPos.value.y
};
};
const stopDrag = () => {
isDragging.value = false;
window.removeEventListener('mousemove', onDrag);
window.removeEventListener('mouseup', stopDrag);
};
</script>
拖拽排序实现
实现列表拖拽排序需要处理元素的相对位置变化。
<template>
<div
v-for="(item, index) in items"
:key="item.id"
draggable="true"
@dragstart="dragStart(index)"
@dragover.prevent="dragOver(index)"
@drop="drop(index)"
>{{ item.text }}</div>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ id: 1, text: '项目1' },
{ id: 2, text: '项目2' }
]);
let draggedIndex = null;
const dragStart = (index) => {
draggedIndex = index;
};
const dragOver = (index) => {
if (draggedIndex !== index) {
const draggedItem = items.value[draggedIndex];
items.value.splice(draggedIndex, 1);
items.value.splice(index, 0, draggedItem);
draggedIndex = index;
}
};
const drop = () => {
draggedIndex = null;
};
</script>
跨组件拖拽
实现跨组件拖拽需要使用 Vue 的 provide/inject 或全局状态管理。
// 在父组件中
provide('dragContext', {
draggedItem: ref(null),
setDraggedItem: (item) => { draggedItem.value = item; }
});
// 在子组件中
const { draggedItem, setDraggedItem } = inject('dragContext');
const handleDragStart = () => {
setDraggedItem(currentItem);
};






