vue3拖拽实现
Vue3 拖拽实现方法
在Vue3中实现拖拽功能可以通过多种方式完成,包括原生HTML5拖拽API、第三方库如vuedraggable或自定义实现。以下是几种常见方法:
使用HTML5原生拖拽API
HTML5提供了原生的拖拽API,可以通过draggable属性和相关事件实现基础拖拽功能。
<template>
<div
draggable="true"
@dragstart="handleDragStart"
@dragend="handleDragEnd"
>
拖拽元素
</div>
</template>
<script setup>
const handleDragStart = (e) => {
e.dataTransfer.setData('text/plain', '拖拽数据');
};
const handleDragEnd = (e) => {
console.log('拖拽结束');
};
</script>
使用vuedraggable库
vuedraggable是一个基于Sortable.js的Vue3拖拽库,适用于列表拖拽排序等场景。

安装:
npm install vuedraggable@next
使用示例:

<template>
<draggable
v-model="list"
@end="onDragEnd"
>
<div v-for="item in list" :key="item.id">
{{ item.name }}
</div>
</draggable>
</template>
<script setup>
import { ref } from 'vue';
import draggable from 'vuedraggable';
const list = ref([
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
]);
const onDragEnd = () => {
console.log('拖拽完成', list.value);
};
</script>
自定义拖拽实现
通过鼠标事件(mousedown、mousemove、mouseup)实现更灵活的拖拽逻辑。
<template>
<div
class="draggable-item"
@mousedown="startDrag"
:style="itemStyle"
>
自定义拖拽元素
</div>
</template>
<script setup>
import { ref } from 'vue';
const isDragging = ref(false);
const startX = ref(0);
const startY = ref(0);
const offsetX = ref(0);
const offsetY = ref(0);
const itemStyle = ref({
left: '0px',
top: '0px',
});
const startDrag = (e) => {
isDragging.value = true;
startX.value = e.clientX;
startY.value = e.clientY;
window.addEventListener('mousemove', onDrag);
window.addEventListener('mouseup', stopDrag);
};
const onDrag = (e) => {
if (!isDragging.value) return;
offsetX.value = e.clientX - startX.value;
offsetY.value = e.clientY - startY.value;
itemStyle.value = {
left: `${offsetX.value}px`,
top: `${offsetY.value}px`,
};
};
const stopDrag = () => {
isDragging.value = false;
window.removeEventListener('mousemove', onDrag);
window.removeEventListener('mouseup', stopDrag);
};
</script>
拖拽与动画结合
使用Vue的过渡动画(<transition>)或CSS动画增强拖拽体验。
<template>
<draggable v-model="list" @end="onDragEnd">
<transition-group name="list">
<div v-for="item in list" :key="item.id" class="item">
{{ item.name }}
</div>
</transition-group>
</draggable>
</template>
<style>
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateY(30px);
}
</style>
注意事项
- 移动端适配:若需支持移动端,需处理
touchstart、touchmove和touchend事件。 - 性能优化:对于大量拖拽元素,建议使用虚拟滚动(如
vue-virtual-scroller)。 - 无障碍访问:为拖拽元素添加
aria-*属性以支持屏幕阅读器。
以上方法可根据实际需求选择或组合使用。






