一、初步实现上拉触底
1.1 在项目中的 pages.json 文件找到自己要做 上拉触底事件的页面配置 onReachBottomDistance
{
"path" : "goods_list/goods_list",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"onReachBottomDistance": 150 // 上拉触底事件触发的距离
}
}
1.2 在页面调用 上拉触底回调 onReachBottom
onReachBottom() {
// 每次触发上拉触底 请求的页码 自加一
this.queryObj.pagenum ++
// 重新请求数据
this.getGoodsList()
}
1.3 在获取数据的函数中 获取到数据之后不要立即赋值,要将之前的数据与下拉触底获取到的数据合并
async getGoodsList(){
const {message:{total, goods}} = await api.getData("/goods/search", this.queryObj)
// console.log(message)
// 通过 ... 展开运算符 将 旧数据 与 上拉触底获取到的数据合并,重新存储起来
this.goodsList = [...this.goodsList, ...goods]
// 总共有多少条数据 后面会用到
this.total = total
}
二、 节流阀处理
2.1 在 data 中定义 节流阀
data() {
return {
isLoading: false // 节流阀 默认为关闭状态
};
},
2.2 在进入发起请求的函数中 打开节流阀,请求发送出去之后 关闭节流阀,在上拉触底的函数中判断 节流阀为 true/false, 具体代码如下:
// 获取数据
async getGoodsList(){
// 打开节流阀
this.isLoading = true
// 发送请求
const {message:{total, goods}} = await api.getData("/goods/search", this.queryObj)
// console.log(message)
// 关闭节流阀
this.isLoading = false
this.goodsList = [...this.goodsList, ...goods]
this.total = total
}
// 上拉触底事件
onReachBottom() {
// 判断是否正在请求其它数据,如果是,则不发起额外的请求
if(this.isLoading) return
this.queryObj.pagenum ++
this.getGoodsList()
}
三、判断数据是否请求完成,如果请求完成就不应该继续发起请求了
通过公式:(页码数 * 每一页获取数据的条数 >= 总条数)如果符合则说明已经没有数据了
3.1 在上拉触底事件中做判断
onReachBottom() {
// 判断数据是否全部请求完成
if(this.queryObj.pagenum * this.queryObj.pagesize >= this.total) {
return uni.showToast({
title: "数据加载完毕!",
duration: 1500,
icon: "none"
})
}
if(this.isLoading) return
this.queryObj.pagenum ++
this.getGoodsList()
}
四、至此一个完整的上拉触底的关键代码就都写完了,以下是完整代码:
注意:不适合粘贴复制,只是怕大家看前面的关键代码段看的云里雾里,所以贴出完整代码以作对比
<template>
<view>
<view class="goods-list">
<block v-for="(goods, i) in goodsList" :key="i">
<my-goods :goods="goods"></my-goods>
</block>
</view>
</view>
</template>
<script>
import api from '@/api/index.js'
export default {
data() {
return {
queryObj:{
query: '',
cid: '',
pagenum: 1, // 数据的页码
pagesize: 10 // 每一页多少条数据
},
goodsList: [],
total: 0, // 总共多少条数据
isLoading: false
};
},
onLoad(option) {
this.queryObj.query = option.query || ''
this.queryObj.cid = option.cid || ''
// console.log(this.queryObj)
this.getGoodsList()
},
methods:{
// 请求数据的方法
async getGoodsList(){
this.isLoading = true
const {message:{total, goods}} = await api.getData("/goods/search", this.queryObj)
// console.log(message)
this.isLoading = false
this.goodsList = [...this.goodsList, ...goods]
this.total = total
}
},
// 上拉触底事件
onReachBottom() {
// 判断数据全部是否请求完成
if(this.queryObj.pagenum * this.queryObj.pagesize >= this.total) {
return uni.showToast({
title: "数据加载完毕!",
duration: 1500,
icon: "none"
})
}
// 上条数据加载完毕再发起下一次请求
if(this.isLoading) return
// 请求的页数
this.queryObj.pagenum ++
this.getGoodsList()
}
}
</script>
<style lang="scss">
</style>