微信小程序封装上拉加载、下拉刷新组件

javascript/jquery

浏览数:564

2020-5-27

微信小程序封装上拉加载下拉刷新组件

我们有一些页面是有tab切换或者搜索框的(需要定位在顶部,列表滑动时不随列表滚动)。
如果使用fixed固定定位,在iOS是正常的,但是在安卓机上就会出现头部随着下滑。
使用微信小程序组件中的<scroll-view>就不会出现这种情况啦。

效果GIF图

下拉刷新 上拉加载

自定义上拉加载、下拉刷新组件封装

scroll.wxml

<video src="../../"/>
<scroll-view class="message scroll-view client-pool-list" scroll-y="{{true}}" lower-threshold="1" bindtouchstart="touchstart" bindtouchmove="touchmove">
    <view class="pull-refresh {{pull.isLoading ? 'chu' : 'jin'}}" id="pull-refresh">
        <image class="icon-refresh z-index-1" src="{{pull.loading}}" />
        <view class="fs24 pt20 f-color-666 z-index-1">{{pull.pullText}}</view>
    </view>
    <slot></slot> <!-- slot接受内容 -->
    <view class="pull-refresh">
        <image class="icon-refresh z-index-1" wx:if="{{push.isLoading}}" src="{{push.loading}}" />
        <view class="fs24 f-color-666 z-index-1">{{push.pullText}}</view>
        </view>
    </scroll-view>

scroll.wxss

.scroll-view {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}
.icon-refresh {
    width: 100rpx;
    height: 100rpx;
}
.pull-refresh {
    height: 140rpx;
    display: flex;
    justify-content: center;
    align-items: center;
    transition: all .5s ease-in-out;
    overflow: hidden;
}
.chu {
    height: 110rpx;
}
.jin {
    height: 0rpx;
}
.f-color-666 {
    color: #666;
}
.fs24 {
    font-size: 24rpx;
}

scroll.js

Component({
    options: {
        multipleSlots: true, // 在组建定义时的选项中启用多slot支持
    },
    /**
    * 组件的属性列表
    */
    properties: {
        listLength: {
            type: Number,
            value: 0
        },
        pull: {
            type: Object,
            value: {}
        },
        push: {
            type: Object,
            value: {}
        }
    },
    /**组件所在页面的生命周期声明对象 */
    pageLifetimes: {
        show() { // 页面被展示
            this.setData({
                pull: this.properties.pull,
                push: this.properties.push,
            })
        },
    },
    /**
     * 组件的初始数据
     */
    data: {
        pull: {},
        push: {},
        slideStart: [],
        moveTime: 0,
    },
    /**自定义方法 */
    methods: {
        /**开始滑动 */
        touchstart(e) {
            /**记录开始滑动的时间 */
            this.setData({
                slideStart: e.touches[0]
            })
        },
        /**滑动 */
        touchmove(e) {
            let moveTime = new Date().getTime(); // 当前时间
            if (moveTime - this.data.moveTime <= 2000) {
                return
            } else {
                this.setData({
                    moveTime: moveTime
                })
            }
            let slideStart = this.data.slideStart;
            let slideMove = e.touches[0];
            let startX = slideStart.pageX;
            let startY = slideStart.pageY;
            let moveEndX = slideMove.pageX;
            let moveEndY = slideMove.pageY;
            let X = moveEndX - startX;
            let Y = moveEndY - startY;
            if (Math.abs(Y) > Math.abs(X) && Y > 0) { // 从上向下滑
                console.log("top 2 bottom");
                this.pullRefresh()
            } else if (Math.abs(Y) > Math.abs(X) && Y < 0) { // 从下向上滑
                console.log("bottom 2 top");
                this.loadMore()
            }
        },
        /**下拉刷新 */
        pullRefresh(e) {
            this.triggerEvent('refresh', {refresh: true})  // 将refresh通过参数的形式传递给父组件
        },
        /**上拉加载更多 */
        loadMore(e) {
            this.triggerEvent('toload', {toload: true})  // 将toload通过参数的形式传递给父组件
        }
    }
})

scroll.json

/**将 component 字段设为 true 可将这一组文件设为自定义组件 */
{
  "component": true
}

使用自定义组件

home.json

{
    "navigationBarTitleText": "标题", // 标题
    "usingComponents": { // 注册组件
        "tab-nav-roll": "../../components/tab-nav-roll/tab-nav-roll",
        "scroll-y": "../../components/scroll-y/scroll-y" // 引入组件
    },
    "enablePullDownRefresh": false, // 是否使用下拉(false:不使用,true:使用)
    "backgroundTextStyle": "dark" // 下拉模式
}

home.wxml

<scroll-y class="scroll-view" pull="{{pull}}" push="{{push}}" listLength="{{clueData.length}}" bindrefresh="refresh" bindtoload="toload">
    <view class="home-clue-list pb20 pr40 pl40" wx:for="{{clueData}}" wx:for-item="item" wx:for-index="key" wx:key="key">
        ...  内容
    </view>
</scroll-y>

home.wxss

.scroll-view {
    position: absolute;
    top: 570rpx;
    bottom: 0;
    width: 100%;
    flex: 1;
}

home.js

Page({
    data: {
        clueData: [
            {createTime: '2019-11-12 16:33'},
            {createTime: '2019-11-12 14:55'}
        ],
        pull: {
            isLoading: false,
            loading: '../../image/common/pull_refresh.gif',
            pullText: '正在加载'
        },
        push: {
            isLoading: false,
            loading: '../../image/common/pull_refresh.gif',
            pullText: '-上拉加载更多-'
        },
    },
    refresh(e) {
        console.log('刷新', e)
        this.setData({
            'pull.isLoading': true,
            'pull.loading': '../../image/common/pull_refresh.gif',
            'pull.pullText': '正在加载',
        })
        setTimeout(() => {
            this.setData({
                'pull.loading': '../../image/common/finish.png',
                'pull.pullText': '刷新完成'
            })
        }, 4000)
        setTimeout(() => {
            this.setData({
                'pull.isLoading': false,
            })
            console.log('+++++ 刷新完成 +++++')
        }, 6000)
    },
    toload(e) {
        console.log('加载', e),
        this.setData({
            'push.isLoading': true,
            'push.pullText': '正在加载',
            'push.loading': '../../image/common/pull_refresh.gif',
        })
        if (this.data.clueData.length < 30) {
            setTimeout(() => {
                let data = this.data.clueData.concat([
                    {createTime: '2019-11-12 16:33'},
                    {createTime: '2019-11-12 14:55'},
                ])
                this.setData({
                    clueData: data,
                    'push.isLoading': false,
                    'push.pullText': '- 上拉加载更多 -',
                    'push.loading': '../../image/common/finish.png',
                })
                console.log('===== 加载完成 =====')
            }, 2000)
        }
    },
})

其他

有什么疑问可以提出。谢谢

作者:Independent