Vue3 中使用 vuedraggable 实现拖拽排序功能,分组拖拽
- 安装
draggable
npm install vuedraggable@next --save
- 基础用法示例
<template>
<div class="app-container">
<draggable
v-model="list"
item-key="id"
:group="{ name: 'items' }"
@end="handleDragEnd"
>
<template #item="{ element }">
<div class="item-card">
<div class="item-title">{{ element.name }}</div>
<div class="item-content">{{ element.description }}</div>
</div>
</template>
</draggable>
</div>
</template>
<script setup>
import { ref } from 'vue';
import draggable from 'vuedraggable';
const list = ref([
{ id: 1, name: '项目1', description: '描述1' },
{ id: 2, name: '项目2', description: '描述2' },
{ id: 3, name: '项目3', description: '描述3' }
]);
const handleDragEnd = (evt) => {
const { newIndex, oldIndex } = evt;
console.log('从位置' + oldIndex + '移动到' + newIndex);
};
</script>
<style scoped>
.item-card {
border: 1px solid #dcdfe6;
border-radius: 4px;
padding: 15px;
margin-bottom: 10px;
background: #fff;
cursor: move;
}
.item-title {
font-weight: bold;
margin-bottom: 8px;
}
.item-content {
color: #666;
}
</style>
- 重要属性说明
v-model
: 绑定数据源
item-key
: 项目的唯一标识
group
: 分组名称,相同组名的可以互相拖拽
@end
: 拖拽结束事件
@start
: 开始拖拽事件
@change
: 顺序改变事件
- 分组拖拽
<template>
<div class="group-container">
<div v-for="group in groups" :key="group.id" class="group">
<h3>{{ group.name }}</h3>
<draggable
v-model="group.items"
:group="{ name: 'items' }"
item-key="id"
@end="(evt) => handleDragEnd(evt, group)"
>
<template #item="{ element }">
<div class="item-card">
{{ element.name }}
</div>
</template>
</draggable>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import draggable from 'vuedraggable';
const groups = ref([
{
id: 1,
name: '分组1',
items: [
{ id: 1, name: '项目1' },
{ id: 2, name: '项目2' }
]
},
{
id: 2,
name: '分组2',
items: [
{ id: 3, name: '项目3' },
{ id: 4, name: '项目4' }
]
}
]);
const handleDragEnd = (evt, group) => {
const { newIndex, oldIndex } = evt;
console.log(`在分组 ${group.name} 中从位置 ${oldIndex} 移动到 ${newIndex}`);
};
</script>
<style scoped>
.group-container {
display: flex;
gap: 20px;
}
.group {
flex: 1;
padding: 15px;
background: #f5f7fa;
border-radius: 4px;
}
.item-card {
background: white;
padding: 10px;
margin: 5px 0;
border-radius: 4px;
cursor: move;
}
</style>
- 注意事项
确保每个拖拽项都有唯一的 key
使用 @end 事件而不是 @change 事件来处理排序结果
如果需要在拖拽时保存滚动位置,可以在 @start 事件中记录位置
组件卸载时注意清理相关事件监听
- 日常整理!