安装组件
# npm管理器
npm install vuedraggable
# yarn管理器
yarn add vuedraggable
vue 文件引入
<template>
<div class="app-container">
<div>
<!-- 源容器 -->
<draggable class="flex" :list="list" item-key="id" animation='150'
:group="{ name: 'drag-group', pull: 'clone' }" :sort="false" :forceFallback="true" :filter="'.noMove'"
@end="handleDragEnd">
<template #item="{ element }">
<div class="list" :class="element.isIn ? 'noMove' : 'move'"> {{ element.modelName }} </div>
</template>
</draggable>
</div>
<!-- 目标容器 -->
<draggable class="dispose" v-model="listUse" :group="{ name: 'drag-group', pull: '' }" :disabled="false"
:sort="false">
<template #item="{ element }" :filter="'.list'">
<div class="list">{{ element.modelName }}</div>
</template>
</draggable>
</div>
</template>
<script setup name="process">
import draggable from "vuedraggable";
const loading = ref(true)
const state = reactive({
// 全部的数据
list: [],
// 拖拽过来的数据
listUse: [],
})
const { list, listUse } = toRefs(state)
const handleDragEnd = (evt) => {
if (evt.to !== evt.from) { // 跨容器拖拽
const draggedItem = evt.item._underlying_vm_; // 获取拖拽的元素
draggedItem.isIn = true; // 标记为已选中
}
};
async function nowSelectSchoolModuleList() {
// let res = await 获取初始的数据请求()
let res = [
{
"id": 1,
"modelName": "列表1",
},
]
listUse.value = res
return res
}
/** 查询角色列表 */
async function getList() {
loading.value = true
let res = await nowSelectSchoolModuleList()
// let response = await 全部数据请求()
let data = [
{
"id": 1,
"modelName": "列表1",
},
{
"id": 2,
"modelName": "列表2",
},
{
"id": 3,
"modelName": "列表1",
},
]
data.map(item => {
if (res.filter(nowItem => nowItem.id === item.id).length > 0) {
item.isIn = true
} else {
item.isIn = false
}
})
list.value = data
loading.value = false
}
onMounted(() => {
getList()
});
</script>
<style lang="scss" scoped>
.app-container {
width: 100%;
height: 100%;
padding: 20px;
}
.flex {
display: flex;
justify-content: flex-start;
}
.list {
width: 245px;
height: 86px;
background: #FAFAFA;
border-radius: 16px 16px 16px 16px;
border: 1px solid #E9E9E9;
padding: 9px 0;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.noMove {
background: rgba(206, 226, 255, 0.75);
}
.dispose {
width: 1560px;
height: 376px;
background: #F6F6F6;
border-radius: 16px 16px 16px 16px;
border: 2px solid #AEAEAE;
padding: 30px;
margin-top: 13px;
}
</style>
效果图如下:

GIF 2025-8-6 15-26-06.gif