element ui plus 穿梭框实现拖动排序
<template>
<div class="container">
<el-transfer
ref="transferRef"
v-model="dataValue"
:titles="['可选字段', '已选字段']"
:data="transferData"
@left-check-change="leftCheckChange"
@right-check-change="rightCheckChange"
>
<template #default="{ option }">
<span :draggable="!option.disabled" @dragstart="drag($event, option)">
{{ option.label }}
</span>
</template>
</el-transfer>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import Sortable, { SortableEvent } from "sortablejs";
import type {
TransferInstance,
TransferKey,
} from "element-plus/es/components/transfer/index.mjs";
interface Option {
key: string;
label: string;
disabled: boolean;
}
//初始化
const generateData = () => {
const data: Option[] = [];
for (let i = 1; i <= 10; i++) {
data.push({
key: i + "",
label: `Option ${i}`,
// disabled: i % 4 === 0,
disabled: false,
});
}
return data;
};
const transferData = ref<Option[]>(generateData());
const transferRef = ref<TransferInstance>();
const draggingKey = ref<string>("");
const dataValue = ref<string[]>(["1", "2"]);
const transferRightCheckData = ref<string[]>([]);
const transferLeftCheckData = ref<string[]>([]);
const leftCheckChange = (val: TransferKey[]) => {
// 穿梭框左侧多选选中
transferLeftCheckData.value = [...val] as [];
console.log("穿梭框左侧多选选中", val);
};
const rightCheckChange = (val: TransferKey[]) => {
// 穿梭框右侧多选选中
transferRightCheckData.value = [...val] as [];
console.log("穿梭框右侧多选选中", val);
};
const drag = (ev: DragEvent, option: Option) => {
// 赋值当前拖拽的唯一标识
draggingKey.value = option.key;
console.log("drag => ev", ev);
console.log("draggingKey", draggingKey.value);
};
onMounted(() => {
const transferEl = transferRef.value?.$el;
if (!transferEl) return;
const leftPanel = transferEl
.getElementsByClassName("el-transfer-panel")[0]
.getElementsByClassName("el-transfer-panel__body")[0];
const rightPanel = transferEl
.getElementsByClassName("el-transfer-panel")[1]
.getElementsByClassName("el-transfer-panel__body")[0];
const rightEl = rightPanel.getElementsByClassName("el-transfer-panel__list")[0];
Sortable.create(rightEl, {
onEnd: (evt: SortableEvent) => {
const { oldIndex, newIndex } = evt;
const temp = dataValue?.value?.[oldIndex];
if (!temp || temp === "undefined") {
return;
} // 解决右边最后一项从右边拖左边,有undefined的问题
if (dataValue?.value && oldIndex != null && newIndex != null) {
dataValue.value[oldIndex] = dataValue?.value[newIndex];
dataValue.value[newIndex] = temp;
}
},
});
const leftEl = leftPanel.getElementsByClassName("el-transfer-panel__list")[0];
Sortable.create(leftEl, {
onEnd: (evt: SortableEvent) => {
const { oldIndex, newIndex } = evt;
const temp = transferData?.value[oldIndex];
if (!temp || temp === "undefined") {
return;
}
// 解决右边最后一项从左边拖右边,有undefined的问题
if (transferData?.value && oldIndex != null && newIndex != null) {
transferData.value[oldIndex] = transferData.value[newIndex];
transferData.value[newIndex] = temp;
}
},
});
leftPanel.ondragover = (ev: DragEvent) => {
ev.preventDefault();
};
leftPanel.ondrop = (ev: DragEvent) => {
ev.preventDefault();
// 往左拉
const index = dataValue?.value?.indexOf(draggingKey?.value);
if (index !== -1) {
// 如果当前拉取的是选中数据就将所有选中的数据拉到左边选中框内
if (transferRightCheckData?.value?.indexOf(draggingKey?.value) !== -1) {
// 此处为多选执行
transferRightCheckData?.value?.reduce((arr, item) => {
if (arr?.indexOf(item) !== -1) {
// 每次计算将相同的删掉
arr?.splice(arr?.indexOf(item), 1);
}
return arr;
}, dataValue.value);
transferRightCheckData.value = []; // 清除右侧选中的 不然下次向左拉取时会有缓存
// 否则就只拉取当前一个
} else {
dataValue?.value?.splice(index, 1);
}
}
};
rightPanel.ondragover = (ev: DragEvent) => {
ev.preventDefault();
};
rightPanel.ondrop = (ev: DragEvent) => {
ev.preventDefault();
// 右边框里没有当前key值的时候 向右拉
if (dataValue?.value?.indexOf(draggingKey?.value) === -1) {
// 此处为多选执行
// 如果当前拉取的是选中数据就将所有选中的数据拉到右边选中框内
if (transferLeftCheckData?.value?.indexOf(draggingKey?.value) !== -1) {
dataValue.value = dataValue?.value?.concat(transferLeftCheckData.value);
transferLeftCheckData.value = []; // 清除左侧选中的 不然下次向右拉取时会有缓存
} else {
// 否则就只拉取当前一个
dataValue?.value?.push(draggingKey?.value);
}
}
};
});
</script>
<style>
.container {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
</style>
https://blog.csdn.net/qq_43771593/article/details/147010069
浙公网安备 33010602011771号