一般小程序做分頁加載數(shù)據(jù)裳仆,會做一些下拉加載更多、然后上拉刷新的操作孤钦。數(shù)據(jù)放在一個(gè)for循環(huán)里去加載歧斟,數(shù)據(jù)源是一個(gè)數(shù)組對象纯丸。在加載下一頁數(shù)據(jù)時(shí),將下一頁的數(shù)據(jù)拼到當(dāng)前數(shù)組后面静袖。這樣的確可以實(shí)現(xiàn)分頁加載數(shù)據(jù)觉鼻,但是如果數(shù)組中的對象都比較大,那么可能加載個(gè)幾頁數(shù)據(jù)队橙,這個(gè)數(shù)組的大小就超過微信的限制了坠陈。可能會出現(xiàn)
VM429:1 appDataChange 數(shù)據(jù)傳輸長度為 1203320 已經(jīng)超過最大長度 1048576
的異常捐康。
下面分別使用普通的方式和另一種方法解決來處理數(shù)據(jù)分頁加載的問題仇矾。完整項(xiàng)目可以在這里下載到
效果
說明
這個(gè)項(xiàng)目中用來分頁的數(shù)據(jù)都是請求同一段json數(shù)據(jù),這段json的數(shù)據(jù)結(jié)構(gòu)是我自己拼的吹由,實(shí)際在應(yīng)用中若未,可以根據(jù)自己項(xiàng)目需求來分頁請求數(shù)據(jù)。這段數(shù)據(jù)的結(jié)構(gòu)為一個(gè)data對象倾鲫,data對象對應(yīng)的是一個(gè)對象數(shù)組粗合。數(shù)組中每個(gè)對象都是一篇文章的信息,嗯乌昔,就是高中語文書里都要背的那種隙疚。每頁的數(shù)據(jù)是40條。一段json大小為570K磕道。另外供屉,這個(gè)項(xiàng)目是為了表現(xiàn)兩種數(shù)據(jù)加載方式而設(shè)計(jì)的項(xiàng)目,并不是真實(shí)的項(xiàng)目溺蕉。
{
"data": [{
"author": "作者",
"dynasty": "作者朝代",
"title": "文章題目",
"article": "文章的具體內(nèi)容",
"useless_data": "沒什么用的數(shù)據(jù)伶丐,純粹為了增加數(shù)據(jù)長度,能更快查看到異常的拋出疯特。",
"share_times": 0,
"like_times": 0,
"id": "0"
}]
}
數(shù)據(jù)加載頁面中的功能簡介
不論是普通加載還是增強(qiáng)加載哗魂,在頁面的onLoad過程中都先調(diào)用了一個(gè) loadInitData
的方法,用來獲取第一頁數(shù)據(jù)漓雅。
之后點(diǎn)擊頁面底部的加載更多录别,可以加載下一頁數(shù)據(jù),而加載下一頁數(shù)據(jù)使用的是另一個(gè)方法loadMoreData
邻吞。
另外頁面中還可以點(diǎn)擊愛心來增加喜歡次數(shù)likeTap
组题、點(diǎn)擊分享來增加分享次數(shù)shareTap
,這是模擬向服務(wù)器請求更新數(shù)據(jù)抱冷。點(diǎn)擊作者或文章題目來查看文章的詳細(xì)信息viewDetail
崔列。
普通方式分頁加載數(shù)據(jù)
普通、簡單的分頁加載數(shù)據(jù)徘层,是將要展示的數(shù)據(jù)放在一個(gè)數(shù)組中峻呕,通過一個(gè)for循環(huán)將數(shù)據(jù)渲染出來利职。在normalLoading.wxml中趣效,普通加載的模版是這樣的:
<scroll-view scroll-y="true" style = "height:100%;position: relative;" scroll-into-view="{{toView}}" scroll-with-animation = "true">
<view id = "top"></view>
<block wx:for="{{articles}}">
<template is = "articles" data='{{item:item,index:index}}'/> <!--將item和index都傳到模版里去瘦癌,不然模版中獲取不到index-->
</block>
<view id = "bottom"></view>
</scroll-view>
加載初始數(shù)據(jù),推薦放在一個(gè)方法中請求跷敬,因?yàn)槿绻鱿吕⑿虏僮鞯脑捬端剑恍枰诔霭l(fā)下拉刷新操作后,再調(diào)用一下這個(gè)方法就可以了西傀。
/**
* 加載初始數(shù)據(jù),有時(shí)候?yàn)榱颂嵘撁娲蜷_速度斤寇,會將所有數(shù)據(jù)合并到一個(gè)接口中返回,然后列表中的第二頁數(shù)據(jù)開始拥褂,使用其它接口返回娘锁,即分頁獲取數(shù)據(jù)時(shí),僅獲取下一頁的數(shù)據(jù)饺鹃。(這里僅做示例莫秆,因?yàn)槊恳豁摂?shù)據(jù)都取一樣的。在實(shí)際開發(fā)中可以考慮這樣分開悔详。)
*/
loadInitData: function () {
var that = this
var currentPage = 0;
var tips = "加載第" + (currentPage+1) + "頁";
console.log("load page " + (currentPage+1));
wx.showLoading({
title: tips,
})
// 請封裝自己的網(wǎng)絡(luò)請求接口镊屎,這里作為示例就直接使用了wx.request.
wx.request({
url: 'https://raw.githubusercontent.com/lanfeng1993/LoadDataDemo/master/data/data.json',
data: {
},
header: {
'content-type': 'application/json'
},
success: function (res) {
wx.hideLoading();
var data = res.data; // 接口相應(yīng)的json數(shù)據(jù)
var articles = data.data; // 接口中的data對應(yīng)了一個(gè)數(shù)組,這里取名為 articles
console.log(articles);
that.setData({
articles: articles,
currentPage: currentPage
})
}
})
},
請求下一頁數(shù)據(jù)后茄螃,將本地的數(shù)組和新一頁的數(shù)據(jù)拼接起來缝驳,讓小程序去渲染頁面。
/**
* 加載下一頁數(shù)據(jù)
*/
loadMoreData: function () {
var that = this
var currentPage = that.data.currentPage; // 獲取當(dāng)前頁碼
currentPage += 1; // 加載當(dāng)前頁面的下一頁數(shù)據(jù)
var tips = "加載第" + (currentPage+1) + "頁";
console.log("load page " + (currentPage+1));
wx.showLoading({
title: tips,
})
// 請封裝自己的網(wǎng)絡(luò)請求接口归苍,這里作為示例就直接使用了wx.request.
wx.request({
url: 'https://raw.githubusercontent.com/lanfeng1993/LoadDataDemo/master/data/data.json',
data: {
},
header: {
'content-type': 'application/json'
},
success: function (res) {
wx.hideLoading();
var data = res.data; // 接口相應(yīng)的json數(shù)據(jù)
var articles = data.data; // 接口中的data對應(yīng)了一個(gè)數(shù)組用狱,這里取名為 articles
// 將新一頁的數(shù)據(jù)添加到原數(shù)據(jù)后面
var originArticles = that.data.articles;
var newArticles = originArticles.concat(articles);
console.log(newArticles);
that.setData({
articles: newArticles,
currentPage: currentPage
})
}
})
},
如果項(xiàng)目中的列表數(shù)量是有限、且數(shù)據(jù)簡單且量小的話拼弃,使用這種方式是沒什么問題的夏伊。但是如果數(shù)據(jù)結(jié)構(gòu)非常復(fù)雜,每個(gè)對象序列化成json后肴敛,對象很大署海,這種方式可能就不太適合了,數(shù)據(jù)請求過多甚至?xí)?dǎo)致小程序沒有響應(yīng)医男。
以本項(xiàng)目為例砸狞,數(shù)據(jù)加載到第六頁沙庐,240條數(shù)據(jù)以后秒梅,再加載第七頁的數(shù)據(jù)時(shí),就會拋出VM429:1 appDataChange 數(shù)據(jù)傳輸長度為 1203320 已經(jīng)超過最大長度 1048576
的異常隅要,因?yàn)閠hat.setData({}})一次性set的數(shù)據(jù)太大了报账,導(dǎo)致數(shù)據(jù)無法設(shè)置研底。
更好的分頁加載數(shù)據(jù)的方式
相對于上面的加載方式埠偿,只需要在數(shù)據(jù)存儲上做一些小的改變,就能實(shí)現(xiàn)加載更多的數(shù)據(jù)榜晦。這個(gè)方法就是再增加一個(gè)數(shù)組冠蒋,用來存放數(shù)據(jù)。上一個(gè)方法是一個(gè)數(shù)組中存放所有的數(shù)據(jù)乾胶,數(shù)據(jù)量很容易就會變大抖剿。這個(gè)方法,將每一頁請求過來的數(shù)據(jù)的引用放到一個(gè)新的數(shù)組dataArray內(nèi)识窿。dataArray[0]存放第一頁數(shù)據(jù)斩郎,dataArray[1]存儲第二頁數(shù)據(jù)。請求新一頁喻频,都只需要更新一組數(shù)據(jù)缩宜,這樣set的數(shù)據(jù)就不會超過微信小程序允許的長度。這個(gè)方法首先在loadInitData時(shí)甥温,清空dataArray锻煌,防止新數(shù)據(jù)與原數(shù)據(jù)沖突。然后將這一頁數(shù)據(jù)放到dataArray[0]中即可窿侈。
loadInitData: function () {
var that = this
var currentPage = 0; // 因?yàn)閿?shù)組下標(biāo)是從0開始的炼幔,所以這里用了0
var tips = "加載第" + (currentPage+1) + "頁";
console.log("load page " + (currentPage + 1));
wx.showLoading({
title: tips,
})
// 刷新時(shí),清空dataArray史简,防止新數(shù)據(jù)與原數(shù)據(jù)沖突
that.setData({
dataArray: []
})
// 請封裝自己的網(wǎng)絡(luò)請求接口乃秀,這里作為示例就直接使用了wx.request.
wx.request({
url: 'https://raw.githubusercontent.com/lanfeng1993/LoadDataDemo/master/data/data.json',
data: {
},
header: {
'content-type': 'application/json'
},
success: function (res) {
wx.hideLoading();
var data = res.data; // 接口相應(yīng)的json數(shù)據(jù)
var articles = data.data; // 接口中的data對應(yīng)了一個(gè)數(shù)組,這里取名為 articles
var totalDataCount = articles.length;
// console.log(articles);
console.log("totalDataCount:"+totalDataCount);
that.setData({
["dataArray["+currentPage+"]"]: articles,
currentPage: currentPage,
totalDataCount: totalDataCount
})
}
})
},
在頁面的渲染上圆兵,與上面的方法也有一些小差別,使用了2個(gè)for循環(huán)來渲染數(shù)據(jù)跺讯。
<scroll-view scroll-y="true" style = "height:100%;position: relative;" scroll-into-view="{{toView}}" scroll-with-animation = "true">
<view id = "top"></view>
<block wx:for="{{dataArray}}" wx:for-item="articles" wx:for-index="dataArrayIndex">
<block wx:for="{{articles}}" wx:for-item="item" wx:key="{{item.id}}" wx:for-index="index">
<template is = "articles" data='{{item:item,index:index,dataArrayIndex:dataArrayIndex}}'/> <!--將item和index都傳到模版里去,不然模版中獲取不到index-->
</block>
</block>
<view id = "bottom"></view>
</scroll-view>
加載下一頁數(shù)據(jù)時(shí)殉农,根據(jù)這頁的下標(biāo)刀脏,將這頁的數(shù)據(jù)放到對應(yīng)下標(biāo)的dataArray中。
/**
* 加載下一頁數(shù)據(jù)
*/
loadMoreData: function () {
var that = this
var currentPage = that.data.currentPage; // 獲取當(dāng)前頁碼
currentPage += 1; // 加載當(dāng)前頁面的下一頁數(shù)據(jù)
var tips = "加載第" + (currentPage + 1) + "頁";
console.log("load page " + (currentPage + 1));
wx.showLoading({
title: tips,
})
// 請封裝自己的網(wǎng)絡(luò)請求接口超凳,這里作為示例就直接使用了wx.request.
wx.request({
url: 'https://raw.githubusercontent.com/lanfeng1993/LoadDataDemo/master/data/data.json',
data: {
},
header: {
'content-type': 'application/json'
},
success: function (res) {
wx.hideLoading();
var data = res.data; // 接口相應(yīng)的json數(shù)據(jù)
var articles = data.data; // 接口中的data對應(yīng)了一個(gè)數(shù)組愈污,這里取名為 articles
// 計(jì)算當(dāng)前共加載了多少條數(shù)據(jù),來證明這種方式可以加載更多數(shù)據(jù)
var totalDataCount = that.data.totalDataCount;
totalDataCount = totalDataCount + articles.length;
console.log("totalDataCount:" + totalDataCount);
// 直接將新一頁的數(shù)據(jù)添加到數(shù)組里
that.setData({
["dataArray[" + currentPage + "]"]: articles,
currentPage: currentPage,
totalDataCount: totalDataCount
})
}
})
},
這種方式加載同樣的數(shù)據(jù)可以加載到1400條轮傍,再往下加載會拋出另一個(gè)異常:Uncaught Dom limit exceeded, please check if there's any mistake you've made.
這個(gè)問題是因?yàn)樾〕绦蛟谶@個(gè)頁面渲染的dom結(jié)構(gòu)太多了暂雹,已經(jīng)超過了上限,這個(gè)問題目前沒有找到什么解決方法创夜。畢竟數(shù)據(jù)也是不能被無限加載的杭跪,小程序內(nèi)也沒有app中列表的復(fù)用的能力。不過相對于第一種方法,只能加載240條數(shù)據(jù)來說涧尿,這種方法能加載1400條數(shù)據(jù)系奉,也還是可以的,不過加載了1400條數(shù)據(jù)后姑廉,這個(gè)列表滾動(dòng)起來也是非橙绷粒卡了。
總結(jié)
雖然實(shí)際項(xiàng)目中數(shù)據(jù)可能不會加載這么多條數(shù)據(jù)庄蹋,但是因?yàn)檫@里每條數(shù)據(jù)對應(yīng)的對象大小實(shí)際上不算特別大瞬内,實(shí)際項(xiàng)目中的數(shù)據(jù)可能會更復(fù)雜迷雪,更多限书。這時(shí)候,為了性能和速度章咧,可以考慮和后端同學(xué)溝通倦西,將數(shù)據(jù)封裝成一個(gè)結(jié)構(gòu)簡單一些的數(shù)據(jù)傳輸對象,不會直接展示出來的數(shù)據(jù)結(jié)構(gòu)就不要在列表中直接傳輸過來赁严,再結(jié)合第二種方法加載數(shù)據(jù)扰柠,應(yīng)該能應(yīng)對大部分情況了。