侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

微信(小程序)  /  管理员 发布于 5年前   514

项目中遇到 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.jsComponent({ properties: {  key: {   type: String,   observer: '_loadMoreData' // _loadMoreData 为分页操作  } }})
                                      
Page({ onReachBottom(){  const key = scene[+this.data.currentTab].key // 对应tab对应key  this.setData({   [key]: random(16)  }) }})

分页组件的实现逻辑

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

  • 上一页还未加载完成(loading = true),不重复加载
  • 当前页面全部加载完(ended = true),不继续加载

具体加载流程为:

  1. page:触发 onReachBottom 事件,修改 pagination组件 key 值
  2. component: key值监听到变化,触发加载事件 _loadMoreData
  3. component: _loadMoreData 中判断满足条件后,触发加载列表函数 this.triggerEvent('getList'),并传入页面参数page 和 size。
  4. page:向model层获取数据。
  5. page:获取数据后,传递给 pagination组件list和total 值。
  6. component:list 监听到变化,判断是否加载完成。

component

// components/pagination/index.jsComponent({ 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

循环列表item

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

 

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

componentGenerics 字段中声明:

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

使用抽象节点:

  

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

对应 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.jsComponent({ 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(){   console.info(`${this.data.name}:start init data`)   this._loadMoreData()   this.setData({    initState: true   })     },  // ...    _endState(val, oldVal) {   if (!this.data.initState) return    // ...   }, }})

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

组件的复用

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

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

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

您可能感兴趣的文章:

  • 微信小程序云开发实现数据添加、查询和分页
  • 微信小程序分页加载的实例代码
  • 微信小程序实现移动端滑动分页效果(ajax)
  • 微信小程序实战之上拉(分页加载)效果(2)
  • 微信小程序模板之分页滑动栏


  • 上一条:
    微信小程序用户授权、位置授权及获取微信绑定手机号
    下一条:
    微信小程序判断用户是否需要再次授权获取个人信息
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 微信模板消息改版后发送规则记录(微信订阅消息参数值内容限制说明)(1个评论)
    • 微信支付v3对接所需工具及命令(0个评论)
    • 2023年9月1日起:微信小程序必须备案才能上线运营(0个评论)
    • 腾讯官方客服回应了:微信好友上限约10000个!(1个评论)
    • 2023年做微信小程序的老铁注意:新增收费项、微信小程序获取手机号也收费了(2个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2017-10
    • 2018-01
    • 2020-03
    • 2021-06
    • 2021-10
    • 2022-03
    • 2023-02
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客