2025-08-06 vue3+vuedraggable": "^4.1.0"实现拖拽

安装组件

# 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";![GIF 2025-8-6 15-26-06.gif](https://upload-images.jianshu.io/upload_images/14506144-891b0edf92c104fc.gif?imageMogr2/auto-orient/strip)

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
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容