vue3+elementPlus穿梭框拖拽

发布于:2025-05-21 ⋅ 阅读:(17) ⋅ 点赞:(0)

安装

npm install sortablejs --save

<template>
    <div class="transfer" ref="transfer">
        <div>
            <el-transfer v-model="inputForm" :data="data" :titles="titles">
                <template #default="{ option }">
                    <div class="pannel-content">
                        <span :draggable="!option.disabled" @dragstart="drag($event, option)">{{ option.label
                            }}</span>
                    </div>
                </template>
            </el-transfer>
            <el-button @click="submit">确定</el-button>
        </div>
    </div>
</template>

<script lang="ts" setup>
import { TransferDataItem } from 'element-plus';
import Sortable from 'sortablejs';
const props = withDefaults(defineProps<{
    data: TransferDataItem[],
    titles?: [string, string]
}>(), {
    data: () => [{
        key: '111',
        label: `选项一`,
        disabled: false,
    }, {
        key: '222',
        label: `选项二`,
        disabled: false,
    }, {
        key: '333',
        label: `选项三`,
        disabled: false,
    }, {
        key: '444',
        label: `选项四`,
        disabled: false,
    }],
    titles: () => ['单个拖拽待选', '已选列表']
})
const data = computed(() => props.data)
const titles = computed(() => props.titles)

const inputForm = ref([] as any)
const draggingKey = ref(null as any)
const transfer = ref<HTMLDivElement | null>(null)
const drag = (ev: DragEvent, option: any) => {
    draggingKey.value = option.key
}
onMounted(() => {
    const leftPanel = transfer?.value?.getElementsByClassName("el-transfer-panel")[0].getElementsByClassName("el-transfer-panel__body")[0] as any;
    const rightPanel = transfer?.value?.getElementsByClassName("el-transfer-panel")[1].getElementsByClassName("el-transfer-panel__body")[0] as any;
    const leftEl = leftPanel?.getElementsByClassName("el-transfer-panel__list")[0]
    const rightEl = rightPanel?.getElementsByClassName("el-transfer-panel__list")[0]
    Sortable.create(rightEl, {
        onEnd: (evt: any) => {
            const { oldIndex, newIndex } = evt;
            const temp = inputForm.value[oldIndex]
            if (!temp || temp === 'undefined') return;// 解决右边最后一项从右边拖左边,有undefined的问题
            inputForm.value[oldIndex] = inputForm.value[newIndex]
            inputForm.value[newIndex] = temp
        }
    })
    Sortable.create(leftEl, {
        onEnd: (evt: any) => {
            const { oldIndex, newIndex } = evt;
            if (oldIndex === newIndex) return;
            const temp = data.value[oldIndex]
            if (!temp || (temp as any) === 'undefined') return;// 解决右边最后一项从右边拖左边,有undefined的问题
            data.value[oldIndex] = data.value[newIndex]
            data.value[newIndex] = temp
        }
    })
    leftPanel.ondragover = (ev: any) => {
        ev.preventDefault()
    }
    leftPanel.ondrop = (ev: any) => {
        ev.preventDefault();
        const index = inputForm.value.indexOf(draggingKey.value)
        if (index !== -1) {
            inputForm.value.splice(index, 1)
        }
    }
    rightPanel.ondragover = (ev: any) => {
        ev.preventDefault()
    }
    rightPanel.ondrop = (ev: any) => {
        ev.preventDefault();
        if (inputForm.value.indexOf(draggingKey.value) === -1) {
            inputForm.value.push(draggingKey.value)
        }
    }
})
function submit() {
    console.log(inputForm.value);

}
</script>
<style scoped lang="scss">
:deep(.el-transfer__button) {
    width: 30px;
}
</style>


网站公告

今日签到

点亮在社区的每一天
去签到