likes
comments
collection
share

小程序下拉刷新、加载更多及数据分页

作者站长头像
站长
· 阅读数 14

前面设计底部导航栏的时候已经简单说了下下拉刷新,现在在列表页面里,不仅要下拉刷新还需要上拉加载更多。

两种思路

实际上实现下拉刷新和上拉加载更多有两种思路:

  • 页面事件处理函数

第一种是是利用小程序提供的 onPullDownRefresh 和 onReachBottom 方法,这是对于一个 Page 来说的方法,在组件中是没法用的,当然也可以向我前面说的,从页面去调用组件页面自定义的下拉和上拉方法。

这里官方文档页面事件处理函数部分写的很详细

developers.weixin.qq.com/miniprogram…

  • 使用 scroll-view

第二中方法就是用 scroll-view 组件了,它提供了 bindscrolltolower 和 bindscrolltoupper 两个方法,支持上拉和下拉,具体同样看下方官方文档。

developers.weixin.qq.com/miniprogram…

看看效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MSU3UUxF-1620465140193)(C:\Users\shiao\AppData\Roaming\Typora\typora-user-images\image-20210508164204847.png)]

这里就不截动图,都差不多,主要看代码实现。

实现方法

因为我们使用到了底部导航栏,所以没办法继续使用页面的 onReachBottom 方法,实际我也没试过。这里用的是 scroll-view 来实现加载更多,至于下拉加载已经有了,就按之前的 onPullDownRefresh 用,当然用 scroll-view 继续做下拉也是可以的,我是觉得没必要。

看看代码

  • WXML
<van-search model:value="{{ value }}" custom-class="search" placeholder="请输入单位名称或签到日期" shape="round"
    bind:search="onSearch" bind:change="searchChange" />

<scroll-view style="height:{{containerHeight}}rpx" scroll-y lower-threshold="100rpx" bindscrolltolower="onReachBottom">
    <block wx:for='{{records}}' wx:key='this'>
        <!-- 解决未填满得时候可以滑动,第一个元素不能有margintop值 -->
        <view wx:if="{{index==0}}" style="height:28rpx"></view>
        <view class='list-item' data-index='{{index}}'>
			<!-- 你的内容 -->
        </view>
    </block>
    <block wx:if="{{isLoadEnd&&records.length==0}}">
        <view class="center-both" style="height:100%">
            <view class="col-center">
                <image style="width:480rpx;height: 400rpx;" src="../../../../assets/icon/empty2x3.png"></image>
                <view class="empty-hint">未搜索到单位~</view>
            </view>
        </view>
    </block>
    <view wx:if="{{isLoadComplete&&records.length!=0}}" class="nomore">没有更多数据了</view>
</scroll-view>

这里主要看 scroll-view 的内容,注意 scroll-y表示纵轴滚动,bindscrolltolower 绑定了加载更多的函数。下面还根据 isLoadEnd 和数据是否长度为零,显示没有数据的提示,isLoadEnd 的作用是限定在获得数据后才提示没有数据。isLoadComplete 字段表示数据已经全部加载完成。

  • WXSS
.search {
    height: 96rpx;
}

.empty-hint {
    font-size: 28rpx;
    font-family: PingFangSC-Regular, PingFang SC;
    font-weight: 400;
    color: #949494;
    line-height: 40rpx;
    margin-top: 48rpx;
}

.nomore {
    width: 100%;
    box-sizing: border-box;
    text-align: center;
    margin: 28rpx 0 0;
    
    font-size: 26rpx;
    font-family: PingFangSC-Regular, PingFang SC;
    font-weight: 400;
    color: #616161;
    line-height: 36rpx;
}

.list-item {
    background: #FFFFFF;
    border-radius: 12rpx;
    margin:  28rpx 32rpx 0;
    padding: 24rpx 32rpx;
    box-sizing: border-box;
}

这里主要就是没有数据提示的样式

  • Page.js
var app = getApp()

Page({

    data: {
        //容器高度 = 屏幕高度 - 顶部高度 - 底部高度 - 28padding - 搜索栏
        containerHeight: app.globalData.screenHeight - app.globalData.topHeight - app.globalData.bottomHeight - 28 - 96,

        pageSize: 20, //请求一页的数据数目
        currentPage: 1, //当前页数
        currentparameter: {}, //当前参数
        isLoadEnd: false, //是否单次加载结束
        isLoadComplete: false, //是否获取到全部数据

        value: "",
        records: [

        ],
    },

    onLoad() {
        this.startPage('')
    },

    getData(searchKey) {
        let that = this
        //获取评估项目
        wx.showNavigationBarLoading() //在标题栏中显示加载
        
        // 测试假数据
        this.fakeRequest()
    },

    fakeRequest() {
        app.log("fakeRequest ============================")
        let that = this

        setTimeout(() => {
            app.log("returnData ============================")
            // 模拟请求数据,并渲染
            let ressult = []
                --app.globalData.retryCount
            for (let i = 1; i <= 20; ++i) {
                if (i > 10 && app.globalData.retryCount < 0) {
                    break
                }
                ressult.push({
					//你的数据
                    ...
                })
            }

            //将新数据加进去,通知本次加载结束
            let records = that.data.records
            if (that.data.currentPage == 1) {
                records = ressult
            } else {
                ressult.forEach(element => {
                    records.push(element)
                });
            }

            that.setData({
                records: records,
                isLoadEnd: true,
                isLoadComplete: ressult.length < that.data.pageSize
            })
            // 数据成功后,停止下拉刷新
            wx.hideLoading()
            wx.stopPullDownRefresh();
            wx.hideNavigationBarLoading()
        }, 1500);
    },

    //重新获取数据
    startPage(searchKey) {
        this.setData({
            records: [],
            currentPage: 1,
            currentparameter: searchKey,
            isLoadEnd: false,
            isLoadComplete: false,
        })
        app.globalData.retryCount = 3 //测试假数据
        this.getData(searchKey)
    },

    //下一页
    nextPage() {
        this.setData({
            currentPage: ++this.data.currentPage,
            isLoadEnd: false,
        })
        wx.showLoading({
            title: '正在加载..'
        })
        this.getData(this.data.currentparameter)
    },

    //下拉刷新
    onPullDownRefresh() {
        this.startPage("")
    },

    //上拉加载
    onReachBottom() {
        //上拉加载中,或者数据加载结束,不应该触发下一页
        if (this.data.isLoadEnd && !this.data.isLoadComplete) {
            this.nextPage()
        }
    },

    onSearch() {
        //关键词搜索
        this.startPage(this.data.value)
    },

    searchChange(e) {
        if (e.detail == '') {
            this.startPage("")
        }
    },
})

这里主要看 onPullDownRefresh 和 onReachBottom两个方法,注意 onReachBottom 方法实际是我们自定义的,代码其他逻辑下面介绍。

重新开始页面

当页面初次进来、下拉刷新或者重新搜索的时候,页面应该是从第一页重新加载的,这里使用 startPage 方法来实现这种逻辑。首先要把数据清空,再把各种标志位恢复,currentparameter记住本次搜索的数据,并启动搜索。

下一页

当不需要重新加载页面,而是加载更多的时候,使用 nextPage 方法加载下一页。这里只需要将当前页面值加一并请求即可,isLoadEnd = false 表示正在加载中。这里没有在列表最底部写一个加载条,而是直接使用 loading 提示加载,其实写个加载条也简单,根据 isLoadEnd 显示就可以。

假数据测试

这里没有直接用真实数据测试,而且代码部分逻辑被我清除了,但是问题不大。主要就是用了一个全局变量控制加载三次,前几次满数据,第三次只有十条数据。拿到数据后需要根据当前页面,判断是将数据全部覆盖,还是在后面追加,同时将对应标志位恢复。

这里尤其注意几个标志位,isLoadEnd 表示加载中,无论请求成功还是失败,切记将 isLoadEnd 复位,而 isLoadComplete 表示数据完全加载完成,在这的判断就是数据不满页,但是如果没有数据以失败的形式返回的话,isLoadComplete 不要忘记复位。

结语

这里的上拉刷新和下拉加载做的很简单,但是扩展起来也还是很方便的,分页的思想还是从安卓那边继承过来的,可惜小程序列表不需要写适配器。

end

完美撒花

转载自:https://juejin.cn/post/7222855604406796346
评论
请登录