赞
踩
前面设计底部导航栏的时候已经简单说了下下拉刷新,现在在列表页面里,不仅要下拉刷新还需要上拉加载更多。
实际上实现下拉刷新和上拉加载更多有两种思路:
第一种是是利用小程序提供的 onPullDownRefresh 和 onReachBottom 方法,这是对于一个 Page 来说的方法,在组件中是没法用的,当然也可以向我前面说的,从页面去调用组件页面自定义的下拉和上拉方法。
这里官方文档页面事件处理函数部分写的很详细
https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html
第二中方法就是用 scroll-view 组件了,它提供了 bindscrolltolower 和 bindscrolltoupper 两个方法,支持上拉和下拉,具体同样看下方官方文档。
https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MSU3UUxF-1620465140193)(C:\Users\shiao\AppData\Roaming\Typora\typora-user-images\image-20210508164204847.png)]
这里就不截动图,都差不多,主要看代码实现。
因为我们使用到了底部导航栏,所以没办法继续使用页面的 onReachBottom 方法,实际我也没试过。这里用的是 scroll-view 来实现加载更多,至于下拉加载已经有了,就按之前的 onPullDownRefresh 用,当然用 scroll-view 继续做下拉也是可以的,我是觉得没必要。
<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 字段表示数据已经全部加载完成。
.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; }
这里主要就是没有数据提示的样式
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
完美撒花
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。