滚动分页加载是非常常见的应用需求与技巧了,本次我们拿小程序的 scroll-view 举例,说明滚动分页的实现。
小程序《动漫二次元图片分享保存工具》为案例,可自行查看效果。
这是小程序框架里面自带的滚动视图,可以设置滚动方向以及监听相关滚动事件。
这是小程序官网的文档,本文只用了框框里面的事件,上面的参数没有设置,简单就好……
框框那个 bindscrolltolower 是当触底(纵向滚动)或触右(横向滚动)触发的事件,如果是 Web 还得自己在 onscroll 类似设置:if (div.scrollTop + div.clientHeight === div.scrollHeight)
所以说小程序超级简单了。
先看事由,关注我的人知道,这个项目一直在轻量更新,因为主要更新的是内容,而内容是数据库的东西,前端增量是很少的(小程序属于前端)。
但是随着后面数据的增加,有些标签带来的图片已经到了接近 50 张,在网络不好或者性能不好的机子上面,极易出现卡顿,尤其是网络差的时候,用户体验简直爆炸(没错,自己的作品都受不了)。
那如果后面几百上千张呢,那还不直接卡死得了。
所以,我们需要分页,当然这个分页和我们说得“分页”有差,这个是滚动自动触发加载后续内容的方案。
上代码:
获取数据渠道不同,解决思路一致
const limit = 10 // 每次请求数目 let skipCount = 0 // 当前需要跳转数目的倍率 let loading = false // 是否在请求中 let noMore = false // 还有没有后续资源
一个一个解释:
简单,就是每次请求多少个过来。不可变,所以用 const。
一个计数器(凡是计数器都需要重置),很明显 limit * skipCount 就是当前需要跳过的数目。
防止多次请求的关键,如果处理不好,容易窜数据。
用来防止已经请求全部了之后,继续走响应函数逻辑,减轻服务器压力。
继续代码:
// 清空控制参数 clearParam() { loading = false skipCount = 0 noMore = false this.setData({ images: [] }) // 先清空 }
如上文所述,你得有个清空重置的渠道(函数),这里 images: []
是清空图片的,嘛,你切换标签总要清空之前资源,不然网络返回之前一直显示之前的内容不舒服吧。
再来:
// 触底事件 scrollBottom() { if (noMore) return skipCount++ this.getImages(this.data.title) }
触底了,那么是该考虑事件逻辑了。
别急,核心在这里:
loading = true // 请求前标记请求中 new AV.Query(className) .descending('updatedAt') .limit(limit) // 请求数量 .skip(skipCount * limit) // 跳过的数量 .find() .then(res => { wx.hideLoading() loading = false // 请求完毕后取消标记 if(res.length < limit) noMore = true // 这里哦,请求到的结果少于预求数量,说明没有存量了 this.setData({ images: this.data.images.concat(Array.from(res, item => item.get('url'))), // 注意,这是跟进数据,所以是拼接数组,千万不要用替换数组…… selectedClass: className }) }) .catch(console.error)
核心行打上了注释,到这里是不是比较清晰了?
不要纠结那个 AV 是不是……那个 AV 是啥,总之就是你获取数据的接口了。
注意点:
前后对比:
看清没?
你说如果不加菊花转根本看不出来?
呐呐呐,这个该行了吧:
一次全部来了。
分批次来。
欢迎关注,如有需要 Web,App,小程序,请留言联系。