小程序的开发流程_小程序分页实践之编写可复用

发布时间:2021-01-07 12:28 作者:jianzhan

摘要: 微信小程序分页查询实践活动之撰写可重复使用分页查询部件 本文关键详细介绍了微信小程序分页查询实践活动之撰写可重复使用分页查询部件,原文中根据实例编码详细介绍的

小程序分页实践之编写可复用分页组件       这篇文章主要介绍了小程序分页实践之编写可复用分页组件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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

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

源码可以查看:

项目需求

具体项目需求:

查看自己相关的会议(页面命名为 meetings) tab切换,分为: “我的会议”(我参加的会议,后面会以 "join" 为 key区分) “我的预约”(我预约的会议,后面会以 "book" 为 key区分)
首次只加载默认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 name="JOIN" key="{{joinKey}}" /pagination /view /tab tab title="我的预约" view pagination name="BOOK" key="{{bookKey}}" /pagination /view /tab /tabs
上一页还未加载完成(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

 !-- pages/user/meetings/index.wxml -- 
 pagination 
 name="BOOK"
 key="{{bookKey}}"
 bind:getList="getBookMeetings"
 list="{{bookMeetings}}"
 total="{{bookTotal}}"
 /pagination 

循环列表item

pagination组件获取了可循环的列表,初始想法是循环slot,但是在slot中却获取不到 item 对象:

 view wx:for="{{list}}" wx:for-item="item" wx:key="index" 
 slot /slot 
 /view 

解决的办法是将每个列表项封装为组件,循环,这样对其他页面的分页具有可拓展性。

componentGenerics 字段中声明:

// components/pagination/index.json
 "componentGenerics": {
 "selectable": true
 // ...

使用抽象节点:

 !-- components/pagination/index.wxml -- 
 view wx:for="{{list}}" wx:for-item="item" wx:key="index" 
 selectable item="{{item}}" /selectable 
 /view 

指定“selectable”具体是哪个组件:

 !-- pages/user/meetings/index.wxml -- 
 pagination 
 generic:selectable="meeting-item"
 // ... 其他属性
 /pagination 

对应 json 文件定义对应 usingComponents :

// pages/user/meetings/index.json
 "usingComponents": {
 "pagination":"/components/pagination/index",
 "meeting-item":"/components/meeting-item/index"

meeting-item 组件接收一个属性 item,这样在 meeting-item 组件中,就可以获取到循环列表的item值,并正常绘制页面。

实现切换懒加载

给pagination添加initImmediately属性,当initImmediately为true时,首次加载页面,并用变量 initState标记是否已经初始化页面过。

// components/pagination/index.js
Component({
 properties: {
 initImmediately: {
 type: Boolean,
 value: true,
 observer: function(val){
 if (val !this.data.initState) {
 this.initData()
 // ...
 data: {
 initState: false, // 是否已经加载过
 // ...
 lifetimes: {
 attached: function () {
 if (this.data.initImmediately){
 this.initData()
 methods: {
 initData(){
 (`${this.data.name}:start init data`)
 this._loadMoreData()
 this.setData({
 initState: true
 // ... 
 _endState(val, oldVal) {
 if (!this.data.initState) return 
 // ...

当currentTab为当前类型的时候,initImmediately 设置为 true。

 !-- pages/user/meetings/index.wxml -- 
 pagination 
 name="JOIN"
 init-immediately="{{currentTab==type['JOIN']}}"
 // ...
 /pagination 
 pagination 
 name="BOOK"
 init-immediately="{{currentTab==type['BOOK']}}"
 // ...
 /pagination 

组件的复用

完成了以上组件,在对其他分页的页面,可以直接复用。比如,实现一个获取全部用户列表的分页,只需要新增一个user-item的组件,像这样调用:

 pagination 
 name="USER"
 key="{{key}}" 
 bind:getList="getUserList" 
 list="{{userList}}" 
 total="{{userTotal}}"
 generic:selectable="user-item"
 /pagination 

具体应用可以查看我写的小demo:。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持凡科。


  • 我国政务服务综合服务平

    十一月2日,我国政务服务综合服务平台手机微信微信小程序发布个人公积金查寻服务。仅用刷脸登陆,全国性3一个省(基层民主区、市辖区)和新疆省生产制造基本建设兵团住户就可以一

  • 手机微信微信小程序连添

    模拟题目:手机上手机微信手机微信微信小程序连添好多个新工作中工作能力,让你的著名知名品牌手机微信微信小程序快速“走红” 手机微信微信小程序经历四年的发展趋势发展趋势

  • 产业园区公司

    模拟题目:产业链产业园区企业|【乘云手机微信微信小程序直播间间】迅速五分鐘公布,独家代理代理商具体实际操作工作中工作经验共享资源! 二月28日,手机上手机微信官方网网公

  • 申通快递公司,脱队中止

    2020年三月12日,阿里巴巴巴巴发布新项目项目投资46.6五亿入股投资项目投资申通,交易开展后将间接性性有着申通14.65%股权。三月26日,申通与新手签署《业务流程步骤合作协议书书》

  • 手机微信本人微信小程序

    据互连网信办息称,最近有手机上手机微信手机微信微信小程序开发设计设计方案者,开发设计设计方案提交的手机微信微信小程序一直审核可是,不知道道道出了什么难点,而以前一