全栈之路-杂篇-前端分页封装优化

  分页在项目中是很普遍存在的,如何封装才能让使用者使用方便,让代码可读性强,之前在写代码的过程中,很少注意这方面的东西,但是随着年龄的增大,作为程序员,面子肯定是要的,就像我想写的一手好字,同样,我也想写出优雅的代码!七月老师的风袖项目,这里的场景是小程序中的分页实现,里面那个分页的封装很值得学习,简单记录一下!

一、微信小程序中分页问题

微信小程序中分页需要考虑哪些方面呢?如何才能做好一个分页呢?以下这些方面存在的问题,你在做小程序中分页的时候考虑到了吗?反正我在做分页的时候是没有考虑这么全面的,没事,一直在学习的路上!

1、一条数据也没有,为空的情况

2、是否是最后一页,还有没有更多数据

3、请求分页数据的累加

这个不像PC端分页,有严格的分页按钮来点击,你点击哪页的数据,我来请求加载哪页的数据就行,小程序中的分页是用户触发上拉触底事件,来进行更多也就是下一页数据的加载的,这里就存在分页数据累加的问题,需要将已经请求的数据和请求的下一页数据进行累加,然后使用setData()方法进行重新渲染,显示出来,例如:总共有100条数据,第一次加载1-20,第二次加载21-40 显示1-40数据 ... 直到100数据加载完成,提示用户加载完成,没有更多数据

4、分页数据的加载状态

  非分页数据  a 正在加载  b 空

  分页数据      a 正在加载  b 加载完成  c 空

5、上滑触低,加载分页数据,避免用户重复发送过多请求,导致数据库查询次数过多,数据库崩溃

二、代码实现

将分页相关的方法封装成Paging类,调用使用方直接实例化Paging类。然后调用getMoreData()方法进行分页数据的请求

1、paging类整体结构搭建(毛坯房)

(1)封装类的时候首先明确需求,这里的具体就是想要获取到分页数据,那么Paging类中需要一个方法来实现这个需求

(2)getMoreData()方法 相当于Generator 生成器中的next方法

(3)参数如何处理 如何传递到Paging类中 这里用到的是constructor 构造器 初始化一些必要的参数

 1 class Paging{
 2   start
 3   count
 4   url
 5 
 6   constructor(url, count, start){
 7     this.count = count
 8     this.start = start
 9     this.url = url
10   }
11   getMoreData(){
12     //生成器 generator
13   }
14 }

2、Paging类主方法简单封装(改水,改电,铺地板)

(1)看看最重要的getMoreData()方法,如何进行数据的获取 这里首先需要考虑的就是数据锁的问题,封装_getLocker()和_releaseLocker()方法

(2)尝试着将数据锁加到getMoreData方法中

(3)新建一个真正的获取数据的方法 _actualGetData()方法

 1 class Paging{
 2   start
 3   count
 4   url
 5   locker = false //创建locker属性
 6 
 7   constructor(url, count, start){
 8     this.count = count
 9     this.start = start
10     this.url = url
11   }
12   getMoreData(){
13     //生成器 generator
14     if(!this._getLocker()){
15       return
16     }
17     this._actualGetData()
18     this._releaseLocker()
19   }
20 
21   _actualGetData(){
22     // 真实获取数据的方法 需要调用Http的request方法 传递一个Object参数对象
23   }
24 
25   _getLocker(){
26     // 获取锁
27     if(this.locker){
28       return false
29     }
30     this.locker = true
31     return true
32   }
33   _releaseLocker(){
34     this.locker = false
35   }
36 }

3、获取真实数据的方法封装(刷白,吊天花板,吊灯)

(1)首先需要考虑的是 调用方需要传递请求参数、url、请求方式,需要封装成一个Object对象 这里就是req,将原来的url参数换成req

(2)url 例:v1/spu/latest?start=0&count=10 后面的参数需要进一步的封装,才能使用方便 使用方只需要传递 url:v1/spu/latest 这种就行

(3)getCurrentReq() 方法中,当频繁的进行调用的时候,我们从this.req中取出url,可能导致url重复拼装,最终得到错误的url 解决方法是重新提取出url参数

(4)对返回结果的封装,返回特定的一个数据结构

(5)对于moreData的判断 写在函数中,因为很多地方需要使用,这里的处理方式是将moreData封装成一个属性

(6)处理累加器的accumulator 封装为一个属性 写一个累加的方法进行累加操作

(7)调用请求之前进行moreData的判断

  1 import {
  2   Http
  3 } from "./http";
  4 class Paging {
  5   start
  6   count
  7   req
  8   locker = false //创建locker属性
  9   url // 添加url属性,解决url重复叠加问题
 10   moreData = true
 11 
 12   constructor(req, count, start) {
 13     this.count = count
 14     this.start = start
 15     this.req = req
 16     this.url = req.url
 17   }
 18   async getMoreData() {
 19     if(!this.moreData){
 20       return
 21     }
 22     //生成器 generator
 23     if (!this._getLocker()) {
 24       return
 25     }
 26     const data = await this._actualGetData()
 27     this._releaseLocker()
 28     return data
 29   }
 30 
 31   async _actualGetData() {
 32     // 真实获取数据的方法 需要调用Http的request方法 传递一个Object参数对象
 33     const req = this._getCurrentReq()
 34     let paging = await Http.request(this.req)
 35     if (!paging) {
 36       return null
 37     }
 38     if (paging.total === 0) {
 39       // 不存在分页数据
 40       return {
 41         empty: true,
 42         items: [],
 43         moreData: false,
 44         accumulator: []
 45       }
 46     }
 47     // 对moreData进行判断 因为这个变量需要很多地方用 把这个属性封装成属性
 48     this.moreData = this._moreData(paging.total_page, paging.page)
 49     if (this.moreData) {
 50       this.start += this.count
 51     }
 52     // 累加操作
 53     this._accumulate(paging.items)
 54     return {
 55       empty:false,
 56       items:paging.items,
 57       moreData:this.moreData,
 58       accumulator:this.accumulator
 59     }
 60   }
 61 
 62   _accumulate(){
 63     // 分页数据累加的方法
 64     this.accumulator = this.accumulator.concat(items)
 65   }
 66 
 67   _moreData(totalPage, pageNum) {
 68     // 总页数 当前页码
 69     return pageNum < totalPage - 1
 70   }
 71 
 72   _getCurrentReq() {
 73     // 封装req参数
 74     let url = this.url
 75     const params = `start=${this.start}&count=${this.count}`
 76     if (url.includes('?')) {
 77       url += '&' + params
 78     } else {
 79       url += '?' + params
 80     }
 81     thi.req.url = url
 82     return this.req
 83   }
 84 }
 85 
 86 _getLocker() {
 87   // 获取锁
 88   if (this.locker) {
 89     return false
 90   }
 91   this.locker = true
 92   return true
 93 }
 94 _releaseLocker() {
 95   this.locker = false
 96 }
 97 }
 98 
 99 export {
100   Paging
101 }

4、封装完成

其他操作请自行完成!!!

 

 内容出处:七月老师《从Java后端到全栈》视频课程

七月老师课程链接:https://class.imooc.com/sale/javafullstack

posted @ 2019-11-16 21:27  ssc在路上  阅读(557)  评论(0编辑  收藏  举报