在 Vue 3 项目中实现列表拖拽排序功能,支持用户通过鼠标或触摸手势对任意样式的自定义列表进行拖动排序,内置平滑的过渡动画。无论是表格组件还是复杂布局的列表,都可轻松实现拖拽重排。列表数据在拖动过程中会自动更新,便于与服务端交互同步排序结果。即使列表区域出现滚动条,仍支持“丝滑”拖拽体验,支持元素拖动至可视区域边缘时自动滚动。该功能兼容 PC 网站和移动端 H5 页面,确保多端一致的交互体验。
相关文档:
中文文档:https://www.itxst.com/vue-draggable-next/tutorial.html
插件文档:https://github.com/SortableJS/Vue.Draggable
包安装方式:
yarn add vuedraggable@next
npm i -S vuedraggable@nextnpm i vuedraggable --save
属性
属性名称 | 说明 |
---|---|
group | 如果一个页面有多个拖拽区域,通过设置group名称可以实现多个区域之间相互拖拽 或者 { name: "...", pull: [true, false, 'clone', array , function], put: [true, false, array , function] } |
sort | 是否开启排序,如果设置为false,它所在组无法排序 |
delay | 鼠标按下多少秒之后可以拖拽元素 |
touchStartThreshold | 鼠标按下移动多少px才能拖动元素 |
disabled | :disabled= "true",是否启用拖拽组件 |
animation | 拖动时的动画效果,如设置animation=1000表示1秒过渡动画效果 |
handle | :handle=".mover" 只有当鼠标在class为mover类的元素上才能触发拖到事件 |
filter | :filter=".unmover" 设置了unmover样式的元素不允许拖动 |
draggable | :draggable=".item" 样式类为item的元素才能被拖动 |
ghost-class | :ghost-class="ghostClass" 设置拖动元素的占位符类名,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true |
chosen-class | :ghost-class="hostClass" 被选中目标的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true |
drag-class | :drag-class="dragClass"拖动元素的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true |
force-fallback | 默认false,忽略HTML5的拖拽行为,因为h5里有个属性也是可以拖动,你要自定义ghostClass chosenClass dragClass样式时,建议forceFallback设置为true |
fallback-class | 默认false,克隆选中元素的样式到跟随鼠标的样式 |
fallback-on-body | 默认false,克隆的元素添加到文档的body中 |
fallback-tolerance | 按下鼠标移动多少个像素才能拖动元素,:fallback-tolerance="8" |
scroll | 默认true,有滚动区域是否允许拖拽 |
scroll-fn | 滚动回调函数 |
scroll-fensitivity | 距离滚动区域多远时,滚动滚动条 |
scroll-speed | 滚动速度 |
代码:
<template>
<section class="content">
<draggable
v-model="list"
item-key="id"
animation="400"
@change="change"
@start="start"
:move="move"
@end="end"
>
<template #item="{ element, index }">
<div class="row">
<span>{{ element.name }}</span>
<span>({{ element.id }})</span>
</div>
</template>
</draggable>
</section>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import draggable from 'vuedraggable'
const list = ref([
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
{ id: 3, name: 'C' },
{ id: 4, name: 'D' },
{ id: 5, name: 'E' },
{ id: 6, name: 'F' },
{ id: 7, name: 'G' },
{ id: 8, name: 'H' },
{ id: 9, name: 'I' },
{ id: 10, name: 'J' }
])
function change(event) {
// console.log('change', event)
}
function start(event) {
console.log('开始拖动')
}
function move(event, originalEvent) {
console.log('已改变位置')
}
function end(event) {
console.log('拖动结束')
}
</script>
<!-- 排序 -->
<style scoped>
/* 根节点 */
.content {
width: 500px;
max-height: 300px;
overflow-y: scroll;
padding: 20px;
background: #fff;
}
/* 列表样式,自行修改 */
.row {
background: rgb(79,205,86);
padding: 10px;
margin-bottom: 10px;
border-radius: 10px;
border: 1px salmon solid;
cursor: move;/* 鼠标手势 */
}
</style>
效果图: