更新记录

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>

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问