小程序网络封装(下)--翻页逻辑

2-2 防抖、截流与分页细节分析

//1.一条数据没有 空
//2.最后一页, 还有没有更多
//3.累加 1-20、21-40
//4.非分页数据: a. 正在加载 loadding b. 空
        分页数据: a.正在加载 b.加载完成 c.没有更多数据
//5.上滑页面触底  加载 避免用户重复发请求 redis
        //按钮 button--防抖和截流: 禁用、倒计时、模态loadding、数据锁
        
        //控制 start count : (ES6以后才推出class)以类为核心的思想封装✅、以函数为核心的思想封装.

2-3 Paging对象

/// 新建 utils->paging.js 文件:
class Paging{
    // 使用Paging时, 不关注细节: 嗨, 我需要下一页的数据, 你返回给我
  // 面向对象的思想
  // Paging对象的设计借鉴了Generator(生成器)
  // 因为Paging要保持状态, 所以Paging对象要以实例化的方式提供给调用方, 不能以静态的方式.  也就是new Paging
  
  start
  count
  url
  locker = false
  
  constructor(url, count=10, start=0){ //指明初始化加载的信息
    this.start = start
    this.count = count
    this.url = url
  }
  
  getMoreData(){
    //getLocker:获取锁的状态, 如果是锁着,就停止加载; 相反就加锁
    //request
    //releaseLocker 放开锁
  }
  
  getLocker(){
    if(this.locker){
      return false
    }
    this.locker = true
    return true
  }

    releaseLocker(){
    this.locker = false
  }
}

2-4 编程原则:多用return提前结束函数,少用else

switch case 替代 if else if
多用return , 少用else

2-5 Paging对象 二

class Paging{
  
  start
  count
  req //跟请求相关的Object对象
  locker = false
    url //保存原始的url, 方便以后拼接判断
  
  constructor(req, count=10, start=0){
    this.start = start
    this.count = count
    this.req = req
    this.url = req.url
  }
  
  getMoreData(){
    //getLocker:获取锁的状态, 如果是锁着,就停止加载; 相反就加锁
    if(!this._getLocker()){
      return 
    }
    //request
    this._actualGetData()
    //releaseLocker 放开锁
    this._releaseLocker()
  }
    
    // v1/spu/latest?start=0&count=10
    _actualGetData(){
    Http.request(this.req)
  }

    //获取当前的req
    _getCurrentReq(){
    let url = this.url //因为url是一个字符串, 不是对象, 不用担心引用类型的问题(后面的操作不会改变this.url的值)
    const params = `start=${this.start}&count=${this.count}`
    // url = v1/spu/latest + '?' + params
    // url = v1/spu/latest?other=abc+'&'+params
    if(url.indexOf('?') !== -1){//判断字符中是否包含 ?
        url += '&' + params
    }
    else{
      url += '?' + params
    }
    this.req.url = url 
    return this.req
  }

  _getLocker(){
    if(this.locker){
      return false
    }
    this.locker = true
    return true
  }

    _releaseLocker(){
    this.locker = false
  }
}

2-6 Paging对象 三

class Paging{
  
  start
  count
  req //跟请求相关的Object对象
  locker = false
    url //保存原始的url, 方便以后拼接判断
  moreData //当前是不是还有更多数据
  
  constructor(req, count=10, start=0){
    this.start = start
    this.count = count
    this.req = req
    this.url = req.url
  }
  
  getMoreData(){
    //getLocker:获取锁的状态, 如果是锁着,就停止加载; 相反就加锁
    if(!this._getLocker()){
      return 
    }
    //request
    this._actualGetData()
    //releaseLocker 放开锁
    this._releaseLocker()
  }

    _actualGetData(){
    const req = this._getCurrentReq()
    let paging = Http.request(req)
    if(!paging){ //如果没有返回,则返回空
      return null//在 http.js中 统一异常处理方案
    }
    
    if(paging.total === 0){
      return{
        empty: true,
        items:[],
        moreData: false,
        accumulator: []
      }
    }
    
    this.moreData = this._moreData(paging.total_page, paging.page)
    
    //HashMap: 比较简单的模型
    //class: 在js中,如果写复杂应用, 也可以考虑给这个结果单独封装定义一个class, 然后return一个class回去.  
        //适用于: 如果返回的Object对象还要包含一些方法的话, 优先建议定义一个class,再把实例化后的对象返回回去.   
        //因为class除了包含数据之外, 还可以包含方法
    
    /*要返回的数据的模型:
    return{// 直接return Object对象或class
        empty: boolean, //是不是空数据
      items: [],//当次请求到的数据
      moreData: boolean, //是不是最后一页
      accumulator: []//累加器: 累加历史请求到的所有items数据
    }
    */
  }
    
    //判断是否有moreData(更多数据)
    _moreData(totalPage, pageNum){
    // 当前页码 pageNum, 从0开始的; totalPage总共多少页.
    return pageNum < totalPage-1
  }

    _getCurrentReq(){
    let url = this.url 
    const params = `start=${this.start}&count=${this.count}`
    if(url.indexOf('?') !== -1){
        url += '&' + params
    }
    else{
      url += '?' + params
    }
    this.req.url = url 
    return this.req
  }

  _getLocker(){
    if(this.locker){
      return false
    }
    this.locker = true
    return true
  }

    _releaseLocker(){
    this.locker = false
  }
}

2-7 Paging对象 四 (最终效果)

import {Http} from "./http";
class Paging{
  
  start
  count
  req //跟请求相关的Object对象
  locker = false
    url //保存原始的url, 方便以后拼接判断
  moreData //当前是不是还有更多数据
  accumulator //累加器(对象是可以保存状态的)
  
  constructor(req, count=10, start=0){
    this.start = start
    this.count = count
    this.req = req
    this.url = req.url
  }
  
  async getMoreData(){
    if(!this.moreData){//如果没有更多数据了直接return
      return
    }
    //getLocker:获取锁的状态, 如果是锁着,就停止加载; 相反就加锁
    if(!this._getLocker()){
      return 
    }
    //request
    const data = await this._actualGetData()
    //releaseLocker 放开锁
    this._releaseLocker()
    return data
  }

    async _actualGetData(){
    const req = this._getCurrentReq()
    let paging = await Http.request(req)
    if(!paging){ //如果没有返回,则返回空
      return null//在 http.js中 统一异常处理方案
    }
    
    if(paging.total === 0){
      return{
        empty: true,
        items:[],
        moreData: false,
        accumulator: []
      }
    }
    
    this.moreData = Paging._moreData(paging.total_page, paging.page)
    if(this.moreData){
      this.start += this.count
    }
    this._accumulate(paging.items) //调用累加器
    return{
      empty: false,
      items: paging.items,
      moreData: this.moreData,
      accumulator: this.accumulator
    }
  }
    
  //操作accumulator对象
  _accumulate(items){
    this.accumulator = this.accumulator.concat(items)
  }  
    
    static _moreData(totalPage, pageNum){//判断是否有moreData(更多数据)
    return pageNum < totalPage-1
  }

    _getCurrentReq(){
    let url = this.url 
    const params = `start=${this.start}&count=${this.count}`
    if(url.indexOf('?') !== -1){
        url += '&' + params
    }
    else{
      url += '?' + params
    }
    this.req.url = url 
    return this.req
  }

  _getLocker(){
    if(this.locker){
      return false
    }
    this.locker = true
    return true
  }

    _releaseLocker(){
    this.locker = false
  }
}

export {
    Paging
}

封装完在模型model的spu-paging.js中测试:

import {Paging} from "../utils/paging"
class SpuPaging{
  static async getLatestPaging(){
    return new Paging(req:{
      url:`spu/latest`
    },count:3)
  }
}
export{
    SpuPaging
}

在页面home.js中调用:

async initBottomSpuList(){
  const paging = await SpuPaging.getLatestPaging()
  const data = paging.getMoreData()
  if(!data){
    return
  }
  ...
},
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容