【微信小程序】setData数据量过大问题与分页刷新加载的实现
站长
· 阅读数 13
我们在开发小程序时,会使用setData
函数将数据从逻辑层发送到视图层,同时改变对应的 this.data
的值(同步)。
setData介绍
Page.prototype.setData(Object data, Function callback)
Object
以 key: value
的形式表示,其中 key
可以以数据路径的形式给出,支持改变数组中的某一项或对象的某个属性,如 array[2].message
,a.b.c.d
,并且不需要在 this.data 中预先定义。
这个特殊用法下文有大用。
setData的限制
- 单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据
- 每秒调用setData的次数不超过20次
setData接口的调用涉及逻辑层与渲染层间的线程通信,通信过于频繁可能导致处理队列阻塞,界面渲染不及时而导致卡顿,应避免无用的频繁调用。
由于setData的限制,为了性能优化,在项目中需要合理使用 setData
分页加载实现
问题: setData单次设置的数据不能超过1024kB,当数据量过大时,如何通过setData实现目的呢?
分析: 通过分批对同一个data中的对象进行修改,而不是覆盖某个data的对象。
常规分页加载
一次性将所有的list数据全部通过setData提交,分页后通过concat来拼接数组,再一次性setData。
代码实现:
index.wxml
<scroll-view class="container" scroll-y="{{true}}" bindscrolltolower="loadMore">
<view class="announce-wrapper" wx:if="{{list.length}}">
<view class="announce-card" wx:for="{{list}}" wx:key="index" data-id="{{item.id}}" bindtap="goDetail">
<view class="announce-card-title">{{item.title}}</view>
<view class="announce-card-date">{{item.create_time}}</view>
<view class="announce-right">
<image src="../../assets/right.png"></image>
</view>
</view>
<view class='loadMore' wx:if="{{loading}}">{{text}}</view>
</view>
<view wx:else class="nodata">暂无公告</view>
</scroll-view>
index.js
Page({
/**
* 页面的初始数据
*/
data: {
list: [],
page: 1,
size: 20,
loading: false,
text: '上拉加载更多'
},
/**
* 生命周期函数--监听页面加载
*/
onShow: function() {
this.initData()
},
/**
* 初始化数据
*/
initData() {
this.setData({
page: 1
})
this._getData()
},
// 接口数据
_getData() {
const data = {
page: this.data.page,
size: this.data.size
}
getInfoList(data).then(res => {
const contentList = res.list
if (contentList.length) {
if (this.data.page == 1) {
this.setData({
list: []
})
}
// 判断最后一页
if (res.pageNum == res.pages) {
this.setData({
list: this.data.list.concat(contentList),
loading: false
})
} else {
this.setData({
list: this.data.list.concat(contentList),
loading: true
})
}
} else {
wx.showToast({
title: '无数据',
icon: 'none'
})
}
})
},
// 加载更多
loadMore() {
if (this.data.loading) {
this.setData({
page: this.data.page + 1
})
this._getData()
}
}
})
这种方法在数据量少时适用,一旦数据量过大就会出现页面卡顿和空白。
优化后的分页加载
将listArr列表数据分组后存放在页面中,需要数据时,提交指定listArr中指定位置的数据,只需要加载本次需要的数据。
优化的重点依据就是: setData函数支持改变数组中的某一项或对象的某个属性
list.js
Page({
// 页面的初始数据
data: {
pageNum: 0,// 当前页数
pageSize: 10,// // 每页数据条数
listArr: [],// 列表二维数组
total: 0, // 总条数
pages: 0, // 总页数
},
// 生命周期函数--监听页面加载
onLoad: function () {
this.loadInitData();
},
// 加载初始页数据
loadInitData() {
// 刷新时,清空listArr,防止新数据与原数据冲突
this.setData({
listArr: [],
pageNum: 1
})
this.initData()
},
// 初始化数据
initData() {
const { pageNum, pageSize } = this.data;
const data = {pageNum:pageNum,pageSize:pageSize};
getData(data).then(res => {
this.setData({
total: res.data.total,
pages: res.data.pages,
[`listArr[${pageNum - 1}]`]: res.data.list // 动态修改数组某一项的值,需要加中括号
})
})
},
// 加载新数据
loadMore: function(){
let { pageNum } = this.data;
pageNum += 1;
this.setData({
pageNum: pageNum
})
this.initData();
},
// 监听用户下拉动作
onPullDownRefresh() {
this.loadInitData()
},
// 页面上拉触底事件的处理函数
onReachBottom() {
const { pageNum, pages } = this.data
if (pageNum < pages) {
this.loadMore()
} else {
dd.showToast({
content: '没有更多数据了',
})
}
},
})
list.wxml
<view class="coupon-list" a:if="{{listArr.length>0}}">
<scroll-view>
<block a:for="{{listArr}}" a:key="index" a:for-item="caption">
<view a:if="{{caption.length}}">
<block a:for="{{caption}}" a:key="index">
<coupon-card item="{{item}}" type="{{currentIndex}}" onClick="goDetail" onCancel="cancelApprove" onApprove="handleApprove"></coupon-card>
</block>
</view>
<va-empty a:else text="暂无数据" />
</block>
</scroll-view>
</view>
<va-empty a:else text="暂无数据" />
这种方法在钉钉小程序中同样可以使用。