介绍
本来想用vuedraggable的,但是项目一直报错,想着用到的功能只是简单的拖动排序,所以自己写一个。
此组件不影响原来的布局。
备注:
wrapClass:之前的容器class
item插槽里面放原来需要遍历的元素
用法
// 使用组件
<template>
<Draggable v-model="list" wrapClass="wrap">
<template #item="item">
<!-- 这是list的item -->
{{item}}
</template>
</Draggable>
</template>
<script lang="ts" setup>
// 引入组件
import Draggable from "@/components/Draggable/index.vue";
import { ref } from "vue"
const list = ref([{name:1,id:1},{name:2,id:2}]);
</script>
<style lang="scss" scoped>
.wrap{
display:flex;
}
</style>
<template>
<TransitionGroup name="draggable" tag="div" class="draggable-wrap" :class="wrapClass ? wrapClass : ''">
<div v-for="(item, i) in list" :key="item.id" :draggable="props.drag" @dragstart="dragstart($event, i)"
@dragenter="dragenter($event, i)" @dragend="dragend" @dragover="dragover">
<slot name="item" :item="item"></slot>
</div>
</TransitionGroup>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
const emit = defineEmits(["update:modelValue"]);
const props = withDefaults(
defineProps<{
modelValue: any, // 排序列表
wrapClass?: any, // 列表类
drag?: boolean // 是否开启拖动,默认开启
}>(),
{
modelValue: [],
wrapClass: "",
drag: true,
}
);
const list = ref<any>([])
watch(() => props.modelValue, () => {
list.value = props.modelValue
}, {
immediate: true
})
let dragIndex = 0
let timeout: any = null
function dragstart(e, index) {
e.stopPropagation()
dragIndex = index
setTimeout(() => {
e.target.classList.add('moveing')
}, 0)
}
function dragenter(e, index) {
e.preventDefault()
// 拖拽事件的防抖 必须防抖不然频繁触发会导致index值不准
timeout = setTimeout(() => {
if (dragIndex !== index) {
const source = list.value[dragIndex];
list.value.splice(dragIndex, 1);
list.value.splice(index, 0, source);
dragIndex = index;
emit("update:modelValue", list);
}
}, 50);
}
function dragover(e) {
e.preventDefault()
e.dataTransfer.dropEffect = 'move'
}
function dragend(e) {
e.target.classList.remove('moveing')
}
</script>
<style lang="scss" scoped>
.draggable-wrap {
position: relative;
padding: 0;
}
.moveing {
opacity: 0;
}
.draggable-move,
.draggable-enter-active,
.draggable-leave-active {
transition: all 0.2s ease;
}
</style>