小程序分页实践之编写可复用分页组件

项目中遇到 tab切换列表,每个tab都需要分页的需求,分页流程具有相似性,于是想将分页封装为组件,方便应用。

组件的应用已写成一个小demo,效果如下图所示(数据用mock模拟):

小程序分页实践之编写可复用分页组件

源码可以查看:wxapp-pagination

项目需求

具体项目需求:

查看自己相关的会议(页面命名为 meetings)

tab切换,分为:

“我的会议”(我参加的会议,后面会以 "join" 为 key区分)

“我的预约”(我预约的会议,后面会以 "book" 为 key区分)

一次加载10条(size=10),拉到底部后,加载下一页(page = page +1)

当然,作为前端,要考虑性能方面的需求:

首次只加载默认tab页的首页,其他tab等到点击到对应tab才开始加载。

回到已加载过的tab页,保留原数据不重新加载。

所以原型图大概就长这样:

小程序分页实践之编写可复用分页组件

逻辑实现

与分页逻辑相关的项目结构如下:

├── components │ ├── meeting-item # 列表item │ └── pagination # 分页组件 ├── model │ └── user.js # 我的相关 model └── pages │ └── user # 我的相关页面 │ ├── meetings # 我的会议(就是tab要分页的页面啦) │ └── ... │ └── vant-weapp

还是用图理一下他们之间的关系吧:

小程序分页实践之编写可复用分页组件

在组件内监听触发分页事件

触发分页的事件是滚动到页面的底部,小程序中,触发该事件是Page页面的onReachBottom事件,但是这个事件只能在Page中触发,所以要将这个触发时机传递给pagination组件。

解决思路是:组件 pagination 内,设置key属性,每当onReachBottom事件触发之后,设置组件属性 key  为一个随机字符串,当组件 pagination 监听到key的变化的时候,做出分页操作。

// components/pagination/index.js Component({ properties: { key: { type: String, observer: '_loadMoreData' // _loadMoreData 为分页操作 } } })

<!-- pages/user/meetings/index.wxml --> <tabs active="{{currentTab}}" bind:change="onChange"> <tab title="我的会议" data-key="{{type['JOIN']}}"> <view> <pagination key="{{joinKey}}" > </pagination> </view> </tab> <tab title="我的预约"> <view> <pagination key="{{bookKey}}" > </pagination> </view> </tab> </tabs>

Page({ onReachBottom(){ const key = scene[+this.data.currentTab].key // 对应tab对应key this.setData({ [key]: random(16) }) } })

分页组件的实现逻辑

触发到达底部之后,需要加载数据。但再加载之前,先满足加载的条件:

上一页还未加载完成(loading = true),不重复加载

当前页面全部加载完(ended = true),不继续加载

具体加载流程为:

page:触发 onReachBottom 事件,修改 pagination组件 key 值

component: key值监听到变化,触发加载事件 _loadMoreData

component: _loadMoreData 中判断满足条件后,触发加载列表函数 this.triggerEvent('getList'),并传入页面参数page 和 size。

page:向model层获取数据。

page:获取数据后,传递给 pagination组件list和total 值。

component:list 监听到变化,判断是否加载完成。

component

// components/pagination/index.js Component({ properties: { name: String, key: { type: String, observer: '_loadMoreData' // _loadMoreData 为分页操作 }, size: { // 每次加载条目数 type: Number, value: 10 }, total: Number, // 页面总数 list: { // 已加载条目 type: Array, observer: '_endState' // 每次加载完新数据,判断数据是否全部加载完成 } }, data: { page: 0, // 当前第几页 loading: false, // 是否正在加载 ended: false // 数据是否已全部加载完成 }, methods: { _loadMoreData(){ const { loading, ended, size } = this.data if (loading) return // 上一页还未加载完成,不加载 if (ended) return // 当前页面全部加载完,不加载 const page = this.data.page + 1 this.setData({ loading: true, // 开始加载新页面loading设置为true page }) // 触发加载下一页,并传入参数 this.triggerEvent('getList', { page, size }) }, _endState(val, oldVal) { const { total, list } = this.properties let ended = false // 判断数据是否全部加载完成 if (list.length >= total) { ended = true } this.setData({ loading: false, // 当前页面加载完成,loading设置为false ended }) } } })

page

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/74a9c49e553c48bbaf165ae604a352f6.html