更新记录
0.3(2023-05-25) 下载此版本
解决微信小程序兼容性问题
0.2(2022-01-21) 下载此版本
添加使用示例
0.1(2022-01-21) 下载此版本
初步版本,基于WXS优化拖动性能,实现元素拖动过程中动态排序。
查看更多平台兼容性
Vue2 | Vue3 |
---|---|
√ | × |
App | 快应用 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节小程序 | QQ小程序 |
---|---|---|---|---|---|---|
app-vue | × | √ | × | × | × | × |
钉钉小程序 | 快手小程序 | 飞书小程序 | 京东小程序 | 鸿蒙元服务 |
---|---|---|---|---|
× | × | × | × | × |
H5-Safari | Android Browser | 微信浏览器(Android) | QQ浏览器(Android) | Chrome | IE | Edge | Firefox | PC-Safari |
---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | × | × | × | × | × |
插件说明
用于对图片或其他item进行拖拽排序的插件,遵循MIT协议。
内部基于WXS实现item流畅跟随touchmove的体验。最初使用的是movable-area和movable-view,发现在安卓上拖拽性能很差,故改为WXS。
本组件必须设定一个不超过页面高度的固定高度,组件内所有图片的累计高度超过固定高度的话,会被隐藏。
关于页面滚动的说明
本来想实现的效果是:当只点击图片,未长按图片触发拖动时,touchmove允许页面滚动;长按图片触发拖动时,禁用页面滚动,同时图片移动到顶部或底部时,代码触发页面滚动。
但因为:
touchmove只能通过.stop.prevent禁用触发滚动,无法按条件进行允许或禁用滚动,所以只能默认禁止触发滚动。
页面滚动的监听只能在外部onPageScroll中监听,组件内无法监听,可通过事件同步到组件内。但经过测试发现parent->component->wxs将页面滚动信息传入组件WXS,再从WXS中触发滚动wxs->component这样传递,性能很低,卡顿非常明显,无法用于实时页面滚动。
scroll-view可通过属性设置滚动位置,同时可通过WXS方便滚动监听,性能较页面滚动稍好一点,但也比较卡,无法上线。
所以目前此插件暂时只能固定高度使用。(要实现需求,估计得用安卓或IOS原生插件的方式了)
PS:其实最好是touchmove中允许在处理函数中通过
event.preventDefault()
或event.stopPropagation()
这种方式来决定是否允许触发滚动,但uniapp为了兼容各端,禁止使用这种方式,必须在xml中写死。(https://uniapp.dcloud.io/vue-basics?id=%e4%ba%8b%e4%bb%b6%e4%bf%ae%e9%a5%b0%e7%ac%a6)
关于item的slot使用
我们知道vue是支持组件通过slot插槽来从外部注入xml的,这个组件最初也是想通过slot来允许外部传入item的具体内容,但因为外部有v-for循环,使用slot的话所有条目都是使用的第一个条目的数据,小程序中slot不支持嵌套在v-for中使用,所以如果需要更复杂的item内容,暂时只能写到组件内部。
WXS支持:APP-vue,H5,微信小程序,QQ小程序。
此组件在微信小程序上测试通过。
不支持:APP-NVUE,百度小程序,支付宝,字节,飞书小程序。
(支付宝和百度小程序可以自己实现SJS或Filter支持来兼容)
其他问题请联系微信:jingyingsuixing
参数说明
参数名 | 类型 | 默认值 | 说明 |
---|---|---|---|
img_list | Array[Object] | [] | 图片列表,列表中每个元素都是对象。图片拖动排序完成时会自动更新此列表 |
img_key | String | path | 图片列表对象中图片的键名 |
showLast | Boolean | true | 是否显示最后面的添加按钮 |
width | Number | 750 | 可拖动区域宽度,单位rpx |
height | Number | 750 | 可拖动区域高度,单位rpx |
viewWidth | Number | 200 | 图片父容器宽度,单位 rpx |
viewHeight | Number | 200 | 图片父容器高度,单位 rpx |
imgMode | String | aspectFit | 图片默认的显示模式 |
marginWidth | Number | 30 | 图片彼此横向间隔,单位rpx |
marginHeight | Number | 30 | 图片彼此纵向间隔,单位rpx |
allowDrag | Boolean | true | 是否允许拖动 |
触发的事件:
addImage: function(){
console.log('you need to add item here');
},
clickItem: function(e, index){
console.log('click item: '+ index, e);
},
longpressItem: function(e){
console.log('long press:', e);
},
sortChange: function(arr){
// 返回的数组还是原始传入的顺序,需要按order_num排序,获得最新排序结果
arr.sort(function(a, b){
return a.order_num - b.order_num;
});
console.log('排序完成:', arr);
}
使用示例
<template>
<view class="content">
<drag-sorts :img_list="items" @add="addImage" :width="700" :height="1200" :viewWidth="190" :viewHeight="280"
class="drag-sort-box" :allowDrag="allowDrag" imgMode="aspectFill"
img_key="path" :showLast="true" @clickItem="clickItem" @longpressItem="longpressItem" @sortChange="sortChange">
<template #footer>
<view class="img-list-footer">
<u-divider half-width="50" border-color="#6d6d6d" bg-color="#f3f4f6">这是底部提示文本</u-divider>
</view>
</template>
</drag-sorts>
</view>
</template>
<script>
import dragSorts from "@/components/miy-drag-sorts/drag-sorts.vue"
export default {
components: {
dragSorts
},
data() {
return {
allowDrag: true,
items: [
{path: 'https://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg'},
{path: 'http://static-aliyun-doc.oss-cn-hangzhou.aliyuncs.com/assets/img/zh-CN/9042359951/p2524.jpg'},
{path: 'https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/4472359951/p59384.jpg'},
{path: 'https://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg'},
{path: 'http://static-aliyun-doc.oss-cn-hangzhou.aliyuncs.com/assets/img/zh-CN/9042359951/p2524.jpg'},
{path: 'https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/4472359951/p59384.jpg'},
]
}
},
onLoad() {
},
methods: {
addImage: function(){
console.log('you need to add item here');
},
clickItem: function(e, index){
console.log('click item: '+ index, e);
},
longpressItem: function(e){
console.log('long press:', e);
},
sortChange: function(arr){
// 返回的数组还是原始传入的顺序,需要按order_num排序,获得最新排序结果
arr.sort(function(a, b){
return a.order_num - b.order_num;
});
console.log('排序完成:', arr);
}
}
}
</script>