通过 sortablejs 工具库,自定义指令来实现拖拽。
npm i sortablejs
directives/draggableTransfer.ts
import Sortable from 'sortablejs'
export function draggableTransfer(app: any) {
app.directive('draggable-transfer', (el, binding) => {
const { value } = binding
const transferDoms = el.querySelectorAll('.el-transfer-panel__list')
transferDoms &&
transferDoms.length > 1 &&
Sortable.create(transferDoms[1], {
handle: '.btn-action', // 触发拖动事件的元素,
draggable: '.el-transfer-panel__item', // 拖动触发时,可拖动的区域
animation: 150,
sort: true,
disabled: false,
onEnd(event: any) {
// 这里可以根据需要更新数据源,例如调用binding.value回调函数传递拖动信息
binding.value?.onDragenChange(event.oldIndex, event.newIndex)
}
})
})
}
directives/index.ts
import type { App } from 'vue'
import { draggableTransfer } from './draggableTransfer'
/**
* 导出指令:v-xxx
* @methods draggableTransfer 穿梭框右侧拖拽排序,用法: v-draggable-transfer
*/
export const setupAuth = (app: App<Element>) => {
draggableTransfer(app)
}
/**
* 导出指令:v-mountedFocus
*/
export const setupMountedFocus = (app: App<Element>) => {
app.directive('mountedFocus', {
mounted(el) {
el.focus()
}
})
}
<template>
<el-transfer
v-draggable-transfer="{ onDragenChange }"
v-model="leftTranList"
:titles="['待选列表', '分类包含产品']"
filterable
:filter-method="filterMethod"
filter-placeholder="搜索关键词"
:data="tranData"
>
<template #default="{ option }">
<div class="flex items-center justify-between">
<div>{{ option.label }}</div>
<img
v-if="leftTranList?.some((e) => e === option.key)"
src="@/assets/svgs/drag.svg"
class="w-[20px] h-[20px] btn-action"
alt=""
srcset=""
/>
</div>
</template>
</el-transfer>
</template>
<script setup lang="ts">
const tranData = ref<any>([
{
label: 'California',
key: 0
},
{
label: 'New York',
key: 1
},
{
label: 'Los Angeles',
key: 2
},
{
label: 'Chicago',
key: 3
},
{
label: 'Houston',
key: 4
},
{
label: 'Phoenix',
key: 5
},
{
label: 'San Antonio',
key: 6
},
{
label: 'Dallas',
key: 7
},
{
label: 'Miami',
key: 8
},
{
label: 'Seattle',
key: 9
},
{
label: 'Boston',
key: 10
}
])
const filterMethod = (query, item) => {
return item.label.toLowerCase().includes(query.toLowerCase())
}
// 左侧穿梭框数据列表
const leftTranList = ref([])
// 拖拽指令回调
const onDragenChange = (newIndex: number, oldIndex: number) => {
//拿出要移动的元素,并从原来的位置移除
const value = leftTranList.value.splice(newIndex, 1)[0]
//将元素插入到新的位置中
leftTranList.value.splice(oldIndex, 0, value)
}
</script>