外观
Draggable 拖拽排序
约 1158 字大约 4 分钟
2025-10-31
此组件用于实现拖拽排序功能,支持多列网格布局、长按拖拽、手柄拖拽等多种交互方式。
基础使用
通过 list 属性传入要排序的数据数组,在数据项中设置 disabled: true 可以禁用该项的拖拽功能。
<template>
<un-draggable
:column="2"
:list="dragList"
@change="onChange"
>
<template #item="{item}">
<view class="grid-item">
<text class="grid-text">{{ item['text'] }}</text>
</view>
</template>
</un-draggable>
</template>
<script setup lang="uts">
import { ref } from 'vue'
const dragList = ref([
{ id: 1, text: "微信" },
{ id: 2, text: "支付宝", disabled: true },
{ id: 3, text: "建设银行" },
{ id: 4, text: "工商银行" },
{ id: 5, text: "农业银行" },
{ id: 6, text: "中国银行", disabled: true },
{ id: 7, text: "招商银行" },
{ id: 8, text: "交通银行" }
])
const onChange = (newList: UTSJSONObject[]) => {
console.log('排序后的列表:', newList)
}
</script>
<style>
.grid-item {
flex: 1;
height: 48px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: white;
border-radius: 8rpx;
margin:10rpx;
}
.grid-text {
font-size: 32rpx;
margin-bottom: 8rpx;
}
</style>多列拖拽排序 - 可关闭
通过 column 属性设置列数,实现网格布局的拖拽排序,启用 closeable 属性添加关闭功能。
<template>
<un-draggable
:list="multiColumnList"
:column="3"
:closeable="true"
>
<template #item="{item, active}">
<view class="grid-item square">
<text class="grid-text" :class="{'text-active': active}">{{item['text']}}</text>
</view>
</template>
</un-draggable>
</template>
<script setup lang="uts">
import { ref } from 'vue'
const multiColumnList = ref([
{ id: 1, text: "A" },
{ id: 2, text: "B" },
{ id: 3, text: "C" },
{ id: 4, text: "D" },
{ id: 5, text: "E" },
{ id: 6, text: "F" }
])
</script>
<style>
.grid-item {
flex: 1;
height: 48px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: white;
border-radius: 8rpx;
margin:10rpx;
}
.square {
aspect-ratio: 1;
}
.text-active {
color: #007AFF;
}
</style>垂直排序 - 手柄拖拽
设置 direction="vertical" 和 :column="1" 实现垂直列表,并使用 handle 插槽自定义拖拽手柄。
<template>
<un-draggable
:list="verticalList"
direction="vertical"
:column="1"
>
<template #item="{ item }">
<view class="vertical-item">
<view class="vertical-icon">
<text class="icon-text">{{item['icon']}}</text>
</view>
<view class="vertical-content">
<text class="vertical-title">{{item['title']}}</text>
<text class="vertical-desc">{{item['desc']}}</text>
</view>
</view>
</template>
<template #handle>
<view class="vertical-handle">
<text class="handle-text">⋮⋮</text>
</view>
</template>
</un-draggable>
</template>
<script setup lang="uts">
import { ref } from 'vue'
const verticalList = ref([
{ id: 1, icon: "📱", title: "手机设置", desc: "管理手机基本设置" },
{ id: 2, icon: "🔔", title: "通知中心", desc: "查看和管理通知" },
{ id: 3, icon: "🔒", title: "隐私安全", desc: "隐私和安全设置" },
{ id: 4, icon: "💾", title: "存储空间", desc: "管理设备存储" },
{ id: 5, icon: "🔋", title: "电池管理", desc: "电池使用情况" },
{ id: 6, icon: "📶", title: "网络设置", desc: "WiFi和移动网络" }
])
</script>
<style>
.vertical-item {
flex: 1;
height: 50px;
display: flex;
flex-direction: row;
align-items: center;
background-color: white;
padding:0 20rpx;
}
.vertical-icon {
width: 80rpx;
height: 80rpx;
background: #f0f0f0;
border-radius: 100px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
.icon-text {
font-size: 40rpx;
}
}
.vertical-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.vertical-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
}
.vertical-desc {
font-size: 24rpx;
color: #666;
}
.vertical-handle {
width: 40px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
.handle-text {
font-size: 32rpx;
color: #999;
font-weight: bold;
transform: rotate(90deg);
}
}
</style>长按拖拽
启用 longpress 属性,需要长按元素才能开始拖拽。
<template>
<un-draggable
:list="longpressList"
:column="2"
longpress
>
<template #item="{item, active}">
<view class="grid-item">
<text class="grid-text">{{item['text']}}</text>
<text class="grid-hint">长按拖拽</text>
</view>
</template>
</un-draggable>
</template>
<script setup lang="uts">
import { ref } from 'vue'
const longpressList = ref([
{ id: 1, text: "北京" },
{ id: 2, text: "上海" },
{ id: 3, text: "广州" },
{ id: 4, text: "深圳" }
])
</script>
<style>
.grid-item {
flex: 1;
height: 48px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: white;
border-radius: 8rpx;
margin:10rpx;
}
.grid-text {
font-size: 32rpx;
margin-bottom: 8rpx;
}
.grid-hint {
font-size: 20rpx;
color: #999;
margin-top: 8rpx;
font-weight: normal;
}
</style>API
Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| list | 数据列表 | Array<UTSJSONObject> | [] |
| column | 列数 | Number | 1 |
| itemHeight | 项目高度 | String | Number | 60 |
| disabled | 是否禁用 | Boolean | false |
| longpress | 是否长按拖拽 | Boolean | false |
| closeable | 是否显示关闭按钮 | Boolean | false |
| direction | 拖拽方向 | Enum | '' |
Events
| 事件名 | 说明 | 类型 |
|---|---|---|
| change | 拖拽排序完成时触发 | Function |
| close | 点击关闭按钮时触发 | Function |
Slot
| 名称 | 说明 | 类型 |
|---|---|---|
| item | 自定义项目内容 | - |
| close | 自定义关闭按钮 | - |
| handle | 自定义拖拽手柄 | - |
Scss 变量
关于组件 SCSS 变量的用法,请参考 组件 SCSS 变量用法。
| 变量名 | 默认值 | 说明 |
|---|---|---|
| $un-draggable-item-z-index | 2 | 项目层级 |
| $un-draggable-item-transition-property | all | 项目过渡属性 |
| $un-draggable-item-transition-duration | 300ms | 项目过渡时长 |
| $un-draggable-item-transition-timing-function | ease | 项目过渡函数 |
| $un-draggable-close-z-index | 10 | 关闭按钮层级 |
| $un-draggable-close-inner-width | 20px | 关闭按钮宽度 |
| $un-draggable-close-inner-height | 20px | 关闭按钮高度 |
| $un-draggable-close-inner-bg-color | #504f4f | 关闭按钮背景色 |
| $un-draggable-close-inner-radius | 100px | 关闭按钮圆角 |
| $un-draggable-disabled-opacity | 0.5 | 禁用状态透明度 |
