無論是微信小程序還是其他前端框架,都會遇到上拉加載(懶加載)和下拉刷新這種問題。其實理清楚什么時候請求數(shù)據(jù)、請求返回的幾種情況,那么做這個懶加載就很簡單了。
一、首先,固定一個包含列表數(shù)據(jù)的view高度,讓它里面列表的數(shù)據(jù)溢出可以滾動:
<scroll-view scroll-y lower-threshold="100" bindscrolltolower="scrollToLower" style="height: 100vh;">
<view wx:for="{{listData}}" wx:key="{{index}}" style="height: 40px;line-height: 40px;border-bottom: 1px solid #f4f4f4;">
Item{{item}}
</view>
</scroll-view>
二、那么列表的數(shù)據(jù)請求就會分成兩種情況:一種是初始化頁面加載的第一頁的數(shù)據(jù);一種是滾動到底部請求的下一頁的數(shù)據(jù)。所以我們在請求時要分成兩種情況,若是第一頁,isPage=false,下一頁的數(shù)據(jù)isPage=true:
//請求數(shù)據(jù)
getData(isPage) {
console.log("需要拼接數(shù)據(jù):", Network.pageData);
let params = {
pageNum: this.data.pageNo,
pageSize: 30
}
//請求
Network.pageData(params,(res,err)=>{
if (isPage) {
//下一頁的數(shù)據(jù)拼接在原有數(shù)據(jù)后面
this.setData({
listData: this.data.listData.concat(res.result)
})
} else {
//第一頁數(shù)據(jù)直接賦值
this.setData({
listData: res.result
})
}
})
},
三、步驟一提到的固定高度的view,它在往上滾動的時候,滾動到一定的位置便請求下一頁的數(shù)據(jù)。我這里設(shè)置了當view距離到底部還有100px時,觸發(fā)請求下一頁的數(shù)據(jù):
//到達底部
scrollToLower: function (e) {
this.setData({
pageNo: this.data.pageNo + 1
})
this.getData(true);
},
四、以上便是基本的上拉加載。通過以上步驟會出現(xiàn)幾個問題,下面提供解決方法:
1、滾動離底部<100px之后,繼續(xù)往底部滾動會一直發(fā)起請求。我們需要在view距離到底部還有100px時,設(shè)置一個全局變量loading,告訴大家我已經(jīng)發(fā)起請求了,等我請求返回的數(shù)據(jù)展示到頁面之后才可以再次發(fā)起請求。將步驟三的代碼改成以下:
//到達底部
scrollToLower: function (e) {
if (!this.data.loading){
this.setData({
loading: true,
pageNo: this.data.pageNo + 1
})
this.getData(true);
}
},
步驟二的代碼改為:
//請求數(shù)據(jù)
getData(isPage) {
console.log("需要拼接數(shù)據(jù):", Network.pageData);
let params = {
pageNum: this.data.pageNo,
pageSize: 30
}
//請求
Network.pageData(params,(res,err)=>{
this.setData({
loading: false
})
if (isPage) {
//下一頁的數(shù)據(jù)拼接在原有數(shù)據(jù)后面
this.setData({
listData: this.data.listData.concat(res.result)
})
} else {
//第一頁數(shù)據(jù)直接賦值
this.setData({
listData: res.result
})
}
})
},
2、如果最后一頁的數(shù)據(jù)都請求完了,再繼續(xù)往下滾動還會發(fā)起請求。設(shè)置一個全局變量noMore,當我請求返回的數(shù)組長度為0時,滾動到底部就不用再發(fā)起請求了。將步驟三的代碼改成以下:
//到達底部
scrollToLower: function (e) {
if (!this.data.loading && !this.data.noMore){
this.setData({
loading: true,
pageNo: this.data.pageNo + 1
})
this.getData(true);
}
},
步驟二的代碼改為:
//請求數(shù)據(jù)
getData(isPage) {
console.log("需要拼接數(shù)據(jù):", Network.pageData);
let params = {
pageNum: this.data.pageNo,
pageSize: 30
}
//請求
Network.pageData(params,(res,err)=>{
this.setData({
loading: false
})
if (isPage) {
//下一頁的數(shù)據(jù)拼接在原有數(shù)據(jù)后面
this.setData({
listData: this.data.listData.concat(res.result)
})
} else {
//第一頁數(shù)據(jù)直接賦值
this.setData({
listData: res.result
})
}
//如果返回的數(shù)據(jù)為空,那么就沒有下一頁了
if (res.result.length == 0) {
this.setData({
noMore: true
})
}
})
},
五、我們接下來完善請求失敗的情況,步驟二的代碼改為:
//請求數(shù)據(jù)
getData(isPage) {
console.log("需要拼接數(shù)據(jù):", Network.pageData);
let params = {
pageNum: this.data.pageNo,
pageSize: 30
}
//請求
Network.pageData(params,(res,err)=>{
this.setData({
loading: false
})
if (err) {//返回失敗
this.setData({
loadingFailed: true
})
return false;
}
if (res.code == 0) {
if (isPage) {
//下一頁的數(shù)據(jù)拼接在原有數(shù)據(jù)后面
this.setData({
listData: this.data.listData.concat(res.result)
})
} else {
//第一頁數(shù)據(jù)直接賦值
this.setData({
listData: res.result
})
}
//如果返回的數(shù)據(jù)為空,那么就沒有下一頁了
if (res.result.length == 0) {
this.setData({
noMore: true
})
}
} else {
//返回失敗
this.setData({
loadingFailed: true
})
}
})
},
步驟一的HTML代碼修改如下:
<scroll-view scroll-y lower-threshold="100" bindscrolltolower="scrollToLower" style="height: 100vh;">
<view wx:for="{{listData}}" wx:key="{{index}}" style="height: 40px;line-height: 40px;border-bottom: 1px solid #f4f4f4;">
Item{{item}}
</view>
<view style="text-align: center;margin: 10px;">
<view wx:if="{{loading}}">加載中...</view>
<view wx:if="{{noMore}}">沒有更多了</view>
<view wx:if="{{loadingFailed}}">數(shù)據(jù)加載失敗,請重試</view>
</view>
</scroll-view>