[VUE2]基于vuedraggable实现拖拽排序卡片
vue transition 参考:https://cn.vuejs.org/v2/api/#transition-group
vuedraggable参考: https://www.npmjs.com/package/vuedraggable
更全的vuedraggable中文文档:https://www.itxst.com/vue-draggable/tutorial.html
Vue.Draggable
是一款基于Sortable.js实现的vue拖拽插件。支持移动设备、拖拽和选择文本、智能滚动,可以在不同列表间拖拽、不依赖jQuery为基础、vue2过渡动画兼容、支持撤销操作,总之是一款非常优秀的vue拖拽组件。
所有的api
属性名称 | 说明 |
---|---|
group | :group= “name”,相同的组之间可以相互拖拽 或者 { name: “…”, pull: [true, false, ‘clone’, array , function], put: [true, false, array , function] } |
sort | :sort= “true”,是否开启内部排序,如果设置为false,它所在组无法排序,在其他组可以拖动排序 |
delay | :delay= “0”, 鼠标按下后多久可以拖拽 |
touchStartThreshold | 鼠标移动多少px才能拖动元素 |
disabled | :disabled= “true”,是否启用拖拽组件 |
animation | 拖动时的动画效果,还是很酷的,数字类型。如设置animation=1000表示1秒过渡动画效果 |
handle | :handle=“.mover” 只有当鼠标移动到css为mover类的元素上才能拖动 |
filter | :filter=“.unmover” 设置了unmover样式的元素不允许拖动 |
draggable | :draggable=“.item” 那些元素是可以被拖动的 |
ghostClass | :ghostClass=“ghostClass” 设置拖动元素的占位符类名,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true |
chosenClass | :ghostClass=“hostClass” 被选中目标的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true |
dragClass | :dragClass="dragClass"拖动元素的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true |
dataIdAttr | dataIdAttr: ‘data-id’ |
forceFallback | 默认false,忽略HTML5的拖拽行为,因为h5里有个属性也是可以拖动,你要自定义ghostClass chosenClass dragClass样式时,建议forceFallback设置为true |
fallbackClass | 默认false,克隆的DOM元素的类名 |
allbackOnBody | 默认false,克隆的元素添加到文档的body中 |
fallbackTolerance | 拖拽之前应该移动的px |
scroll | 默认true,有滚动区域是否允许拖拽 |
scrollFn | 滚动回调函数 |
scrollSensitivity | 距离滚动区域多远时,滚动滚动条 |
scrollSpeed | 滚动速度 |
vue2中的使用
一般搭配Vue自带的transition-group组件使用。
<draggable
class="list-group"
tag="ul"
group="list1"
v-model="flow"
v-bind="dragOptions"
@start="dragStart"
@end="dragEnd"
>
<transition-group type="transition" :name="!drag ? 'flip-list' : null">
<a-card></a-card>
</transition-group>
</draggable>
<script>
import draggable from 'vuedraggable'
export default {
components: {
draggable
},
data: {
...
drag: false
},
methods: {
dragStart() {
console.log('顺序', this.$refs.childComponent)
console.log(this.flow)
this.drag = true
},
dragEnd() {
console.log('顺序', this.$refs.childComponent)
console.log(this.flow)
this.drag = false
},
},
computed: {
dragOptions() {
return {
animation: 200,
group: 'description',
disabled: false,
ghostClass: 'ghost'
}
}
},
}
</script>
<style>
.flip-list-move {
transition: transform 0.5s;
}
</style>
vue3中的使用
<template>
<div class="main">
<draggable
:disabled="!isDraggable"
class="list-group"
v-model="listCopy"
item-key="index"
@start="drag = true"
@end="drag = false"
ghost-class="ghost"
:animation="200"
>
<template #item="{ element, index}">
<div class="list-group-item">
<p><span>[{{ index + 1 }}] </span><span>{{ element.name }}</span></p>
<el-button @click="handleDel(element)" size="small">
删除
</el-button>
</div>
</template>
</draggable>
</div>
</template>
<script setup>
import {ref, toRefs, onMounted} from "vue"
import draggable from "vuedraggable"
const props = defineProps({
list: {
type: Array,
default: () => [
{
id: 1,
name: 1
},
{
id: 2,
name: 2
},
{
id: 3,
name: 3
},
{
id: 4,
name: 4
}
]
},
// 是否允许拖拽
isDraggable: {
type: Boolean,
default: true
}
})
const listCopy = ref(props.list)
const emit = defineEmits(['delete'])
const drag = ref(false)
// const list = ref()
const handleDel = (val) => {
console.log(val)
emit("delete", val);
}
onMounted(() => {
console.log(props.list)
})
</script>
<style scoped>
.main {
/*border: 1px solid black;*/
width: 100%;
}
.wrapper {
display: flex;
justify-content: center;
width: 100%;
}
.item {
width: 100%;
margin: 5px 0;
font-size: 20px;
text-align: center;
padding: 10px;
border: 2px solid black;
background-color: #42b983;
color: #ffffff;
}
.button {
margin-top: 35px;
}
.flip-list-move {
transition: transform 0.5s;
}
.no-move {
transition: transform 0s;
}
.ghost {
opacity: 0.5;
background: #c8ebfb;
}
.list-group {
min-height: 20px;
}
.list-group-item {
margin: 0 0 10px;
cursor: move;
font-size: 16px;
text-align: center;
padding: 5px;
border: 1px solid black;
background-color: #EEEEEE;
/*color: #ffffff;*/
display: flex;
justify-content: space-between;
align-items: center;
}
.list-group-item i {
cursor: pointer;
}
</style>