更新记录
1.0.0(2026-07-28) 下载此版本
首个版本。
- 支持 H5 / App(app-vue) / 微信小程序三端垂直列表拖拽排序
- v-model 双向绑定,触摸拖拽,其余项实时让位,松手归位
- easycom 自动引入,作用域插槽自定义列表项内容
平台兼容性
uni-app(3.7.11)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | × | × | × | √ | × | 4.4 | 12 | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 2.21.4 | - | - | - | - | - | - | - | - | - | - | - |
dazhi-drag-sort 拖拽排序组件
支持 H5 / App(app-vue) / 微信小程序 的拖拽排序组件,v-model 双向绑定,触摸即可拖拽,其余项实时让位、松手平滑归位。
列表项为普通 view + transform:translateY 定位(不使用 movable-view,因其 change 事件在 H5/小程序两端行为不一致,不适合排序场景)。
特性
- 单套代码跨三端(H5 / App / 微信小程序),无需条件编译
v-model双向绑定,兼容 vue2(value/input)与 vue3(modelValue/update:modelValue)- 拖拽过程中其余项实时让位,松手后平滑归位
- 作用域插槽,列表项内容完全自定义
- easycom 自动引入,无需手动 import
安装
将 dazhi-drag-sort 目录放入项目的 uni_modules/ 目录即可,easycom 会自动注册组件,无需手动引入。
基础用法
<template>
<view class="page">
<dazhi-drag-sort v-model="list" :item-height="80" item-key="id">
<template #default="{ item, index, dragging }">
<view class="row" :class="{ 'row--dragging': dragging }">
<text class="row__handle">≡</text>
<text class="row__label">{{ item.name }}</text>
</view>
</template>
</dazhi-drag-sort>
</view>
</template>
<script>
export default {
data() {
return {
list: [
{ id: 1, name: '苹果' },
{ id: 2, name: '香蕉' },
{ id: 3, name: '橙子' },
{ id: 4, name: '葡萄' }
]
}
}
}
</script>
<style>
.row {
display: flex;
align-items: center;
height: 80px;
padding: 0 24rpx;
background: #fff;
border-bottom: 1rpx solid #eee;
}
.row--dragging {
background: #fafafa;
}
.row__handle {
margin-right: 24rpx;
color: #bbb;
font-size: 40rpx;
}
.row__label {
font-size: 30rpx;
}
</style>
使用约定
- 行高需固定且与插槽内容高度一致:
item-height决定每行高度,插槽内的根元素高度必须与之相同(如item-height="80"时插槽根元素height:80px),否则项会错位。当前版本不支持动态行高。 item-key建议提供:列表项应有唯一标识字段(默认id)。字段缺失时回退用 index,会降低重排时的 DOM 复用。- 小程序端列表区不滚:见上方「跨端实现说明」的小程序使用约定。
监听顺序变化
<dazhi-drag-sort
v-model="list"
@change="onchange"
@start="onstart"
@end="onend"
/>
methods: {
onchange({ from, to, list }) {
console.log('从', from, '移到', to, list)
},
onstart({ index }) {
console.log('开始拖拽', index)
},
onend({ from, to }) {
console.log('结束拖拽', from, '->', to)
}
}
API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| value / modelValue | Array | - | 待排序列表,支持 v-model |
| itemKey | String | 'id' |
列表项唯一标识字段名;字段缺失时回退用 index(会降低重排时的 DOM 复用,建议提供) |
| itemHeight | Number / String | 80 |
单行高度(px)。当前版本需固定高度 |
| disabled | Boolean | false |
是否禁用拖拽 |
Events
| 事件 | 参数 | 说明 |
|---|---|---|
| change | { from, to, list } |
顺序变化时触发,from/to 为原索引与新索引 |
| start | { index } |
开始拖拽某项 |
| end | { from, to } |
结束拖拽(无论是否变化) |
Slots
| 插槽 | 作用域参数 | 说明 |
|---|---|---|
| default | { item, index, dragging } |
列表项内容,dragging 表示该项正在被拖拽 |
跨端实现说明
列表项为相对定位的普通 view,拖拽时被拖项 transform 跟随手指,其余项根据落点让位(上/下移一行),松手时重排数据一次。拖拽中 innerList 顺序保持不变,保证 v-for 实例稳定、手势不中断。
拖拽中阻止页面滚动(避免手指拖列表项时页面跟着滚)各端机制不同:
| 端 | 机制 | 调用方需处理 |
|---|---|---|
| H5 | touchstart 时挂一个 {passive:false} 的原生 touchmove 监听器调 preventDefault,松手移除 |
无需 |
| App(app-vue) | 同 H5(webview 渲染) | 无需 |
| 微信小程序 | 根 view 用 @touchmove.stop(编译成 catchtouchmove),静态属性无时序间隙 |
无需 |
小程序端使用约定:
catchtouchmove始终生效,因此列表区域平时也不能触发页面滚动(手指在列表上上下滑不会滚页面)。若列表项数少、一屏放得下,无影响;若列表本身需要长滚动,请将组件放入独立的scroll-view内,并在拖拽到边缘时自行实现自动滚动(后续版本规划)。
路线图:长列表性能(wxs)
当前拖拽跟手由 @touchmove 改 data 驱动,项数较少(约 20 项以内)时三端流畅。项数较多时微信小程序端会因逻辑层桥接掉帧,届时可在保持 API 不变的前提下,把「手指跟随 + 邻项让位」的逐帧位移改用 wxs 响应式在视图层同步完成。调用方代码无需改动。
限制与路线图
当前 1.0.0 版本的已知限制:
- 仅支持垂直列表(横向 / 网格在规划中)
- 行高需固定(动态高度在规划中)
- 未实现长按触发(当前为触摸即拖)
- 仅支持触摸拖拽,PC 端鼠标拖拽未支持(规划中)
- 长列表(约 20 项以上)在微信小程序端可能掉帧,待 wxs 升级解决
路线图:
- [ ] 微信小程序 wxs 响应式升级(长列表性能)
- [ ] PC 端鼠标拖拽支持
- [ ] 动态行高
- [ ] 横向 / 网格布局
- [ ] 长按触发拖拽
- [ ]
disabled状态视觉反馈 - [ ] app-nvue 适配
许可
MIT

收藏人数:
下载插件并导入HBuilderX
赞赏(0)
下载 4
赞赏 0
下载 12466078
赞赏 1936
赞赏
京公网安备:11010802035340号