最佳方式实现微信小程序分页加载数据

一般小程序做分页加载数据,会做一些下拉加载更多、然后上拉刷新的操作。数据放在一个for循环里去加载,数据源是一个数组对象。在加载下一页数据时,将下一页的数据拼到当前数组后面。这样的确可以实现分页加载数据,但是如果数组中的对象都比较大,那么可能加载个几页数据,这个数组的大小就超过微信的限制了。可能会出现
VM429:1 appDataChange 数据传输长度为 1203320 已经超过最大长度 1048576
的异常。

这篇文章开始我们就正式进入小程序的项目开发,这里主要功能包括:网络请求,轮播图,纵向列表,下拉刷新,上拉加载,item点击传值,页面跳转传值.

1.列表(本部分内容出入官方文档)

下面分别使用普通的方式和另一种方法解决来处理数据分页加载的问题。完整项目可以在这里下载到

图片 1效果图.gif图片 2

对于这个功能,微信小程序中并没有提供类似于Android中listview性质的控件,所以我们需要使用
wx:for
控制属性绑定一个数组,用数组中各项的数据重复渲染该组件,来达到列表的效果。

图片 3程序运行效果图片 4普通方式加载图片 5增强方式加载

可以看到只有两个页面-index和info,所以在app.json中配置两个页面路径(注意该文件不能有注释)

<view wx:for="{{array}}">
 {{index}}: {{item.message}}
</view>


Page({
 data: {
 array: [{
  message: 'foo',
 }, {
  message: 'bar'
 }]
 }
})

这个项目中用来分页的数据都是请求同一段json数据,这段json的数据结构是我自己拼的,实际在应用中,可以根据自己项目需求来分页请求数据。这段数据的结构为一个data对象,data对象对应的是一个对象数组。数组中每个对象都是一篇文章的信息,嗯,就是高中语文书里都要背的那种。每页的数据是40条。一段json大小为570K。另外,这个项目是为了表现两种数据加载方式而设计的项目,并不是真实的项目。

{ "pages": [ "pages/index/index", "pages/info/info" ], "window": { "enablePullDownRefresh": true, "backgroundTextStyle": "dark", "navigationBarBackgroundColor": "#000", "navigationBarTitleText": "WeChat", "navigationBarTextStyle": "white" }}

默认数组的当前项的下标变量名默认为index,数组当前项的变量名默认为item,当然也可以通过
wx:for-item 和 wx:for-index 指定。

{ "data": [{ "author": "作者", "dynasty": "作者朝代", "title": "文章题目", "article": "文章的具体内容", "useless_data": "没什么用的数据,纯粹为了增加数据长度,能更快查看到异常的抛出。", "share_times": 0, "like_times": 0, "id": "0" }]}

列表页面需要下拉刷新,所以在index.json中开启下拉刷新,在info中关闭下拉刷新,同时设置title

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
 {{idx}}: {{itemName.message}}
</view>

不论是普通加载还是增强加载,在页面的onLoad过程中都先调用了一个
loadInitData的方法,用来获取第一页数据。

//index.json{ "navigationBarTitleText": "小程序", "enablePullDownRefresh": true}//info.josn{ "navigationBarTitleText": "详情页", "enablePullDownRefresh": false}

wx:for也可以嵌套,下边是一个九九乘法表

之后点击页面底部的加载更多,可以加载下一页数据,而加载下一页数据使用的是另一个方法loadMoreData

轮播图由wx:for和<swiper-item>配合使用,wx:for="{{banners}}"指定数据源数组,interval="1000"指定自动切换的间隔,item为当前项的数据,index为下标,banners为js中的数据源,当js调用setdata并改变banners时,轮播图会刷新

<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="i">
 <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j">
 <view wx:if="{{i <= j}}">
  {{i}} * {{j}} = {{i * j}}
 </view>
 </view>
</view>

另外页面中还可以点击爱心来增加喜欢次数likeTap、点击分享来增加分享次数shareTap,这是模拟向服务器请求更新数据。点击作者或文章题目来查看文章的详细信息viewDetail

<swiper indicator-dots="true" autoplay="true" interval="3000"> <block wx:for="{{banners}}"> <swiper-item> <image src="{{item.url}}" mode="aspectFill" bindtap="itemClick" /> </swiper-item> </block></swiper>

block wx:for

普通、简单的分页加载数据,是将要展示的数据放在一个数组中,通过一个for循环将数据渲染出来。在normalLoading.wxml中,普通加载的模版是这样的:

  • swiper组件提供一些属性,如自动切换,时间间隔,指示器等等

类似block
wx:if,也可以将wx:for用在<block/>标签上,以渲染一个包含多节点的结构块。例如:

<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>

小程序不直接提供列表组件(如Android中的ListView,RecycleView),需要通过wx:for="{{listData}}来重复渲染形成列表,原理同样也是绑定数组,数组更新时刷新列表

<block wx:for="{{[1, 2, 3]}}">
 <view> {{index}}: </view>
 <view> {{item}} </view>
</block>

加载初始数据,推荐放在一个方法中请求,因为如果要做下拉刷新操作的话,只需要在出发下拉刷新操作后,再调用一下这个方法就可以了。

 <view > <block wx:for="{{listData}}"> <view > <image src="%20{{item.url}}%20" mode="aspectFill" bindtap="itemClick" /> <view > <text >{{item.type}}</text> <view > <text >{{item.who}}</text> <text >{{item.desc}}</text> </view> </view> </view> </block> </view>

wx:key

/** * 加载初始数据,有时候为了提升页面打开速度,会将所有数据合并到一个接口中返回,然后列表中的第二页数据开始,使用其它接口返回,即分页获取数据时,仅获取下一页的数据。(这里仅做示例,因为每一页数据都取一样的。在实际开发中可以考虑这样分开。) */ loadInitData: function () { var that = this var currentPage = 0; var tips = "加载第" + (currentPage+1) + "页"; console.log("load page " + (currentPage+1)); wx.showLoading({ title: tips, }) // 请封装自己的网络请求接口,这里作为示例就直接使用了wx.request. wx.request({ url: 'https://raw.githubusercontent.com/lanfeng1993/LoadDataDemo/master/data/data.json', data: { }, header: { 'content-type': 'application/json' }, success: function  { wx.hideLoading(); var data = res.data; // 接口相应的json数据 var articles = data.data; // 接口中的data对应了一个数组,这里取名为 articles console.log; that.setData({ articles: articles, currentPage: currentPage }) } }) },
  • 列表同样使用for来重复渲染,不同的是不需要<swiper-item>来包裹
  • 可以使用wx:key="_id"来指定item的唯一性,如果不指定,微信会抛一个警告,但不会影响程序运行,具体wx:key的原理可查看官方文档
  • 建议动态列表指定wx:key,这样效率会比较高,并且不会丢失item中的状态

如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如
<input/> 中的输入内容,<switch/> 的选中状态),需要使用
wx:key 来指定列表中项目的唯一的标识符。

请求下一页数据后,将本地的数组和新一页的数据拼接起来,让小程序去渲染页面。

轮播图需要一个数组,列表需要一个数组,还需要记录当前页面,所以index的data部分:

wx:key 的值以两种形式提供

/** * 加载下一页数据 */ loadMoreData: function () { var that = this var currentPage = that.data.currentPage; // 获取当前页码 currentPage += 1; // 加载当前页面的下一页数据 var tips = "加载第" + (currentPage+1) + "页"; console.log("load page " + (currentPage+1)); wx.showLoading({ title: tips, }) // 请封装自己的网络请求接口,这里作为示例就直接使用了wx.request. wx.request({ url: 'https://raw.githubusercontent.com/lanfeng1993/LoadDataDemo/master/data/data.json', data: { }, header: { 'content-type': 'application/json' }, success: function  { wx.hideLoading(); var data = res.data; // 接口相应的json数据 var articles = data.data; // 接口中的data对应了一个数组,这里取名为 articles // 将新一页的数据添加到原数据后面 var originArticles = that.data.articles; var newArticles = originArticles.concat; console.log(newArticles); that.setData({ articles: newArticles, currentPage: currentPage }) } }) },
Page({ data: { banners: [],//轮播图数据源, pageNum: 1,//当前页码 listData: []//列表数据 })}
  1. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property
    的值需要是列表中唯一的字符串或数字,且不能动态改变。

  2. 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item
    本身是一个唯一的字符串或者数字,如:
    当数据改变触发渲染层重新渲染的时候,会校正带有 key
    的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website