你知道在小程序中使用上拉触底如何实现节流吗?

486 阅读3分钟

引子

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

在开发小程序时,我们时常要使用到上拉触底,但是在上拉触底事件中,除了使用onReachBottom()函数,我们还需要做节流处理,以防止频繁触发该事件导致频繁发起请求; 阅读本文大约需要 5min

场景

现在项目中有个需求是采用流水屏页面,让用户每次滑动屏幕触底时自动加载数据,从而实现无限加载;但是在滑动过程中时常会发生频繁发送请求,因此我们要让用户就算一直滑动到底部,也只让其每次滑动底部的只执行一次,从而达到节流的效果;

代码示例

我们先来看一下项目需求大概:

后端每次根据前端传递的页数返回数据,前端接收后实现拼接,再配合上拉触底实现无限滑动

功能代码如下:

页面初始数据
  data: {
     shopList: [], // 列表数据
     page: 1, // 当前页
     pageSize: 10, // 每页条数
     total: 0, // 总页数
   },
请求数据代码块
 getShopList() {
     wx.request({
       url: 'www.xxx.com/api',
       method: "GET",
       data: {
         _page: this.data.page, // 当前的页数
         _limit: this.data.pageSize // 总页数
       },
       // 成功执行函数
       success: ({ data: res, header }) => {
         this.setData({
           // 新数据拼接旧数据,采用es6展开运算符,就不多说了
           shopList: [...this.data.shopList, ...res],
           // 获取总页数 (其实不用每次都获取,因为是固定的)
           total: header['X-Total-Count'] - 0
         })
       }
     })
   },
   // 页面初始执行渲染
   onLoad: function (options) { this.getShopList() },
上拉触底加载代码块
 // .js 文件
  onReachBottom() {
      // 判断数据是否加载完毕
      if (this.data.page * this.data.pageSize >= this.data.total) { return ... }
      
     // 每次触底使页数 +1
     this.setData({
       page: this.data.page + 1
     })
     // 让其重新获取
     this.getShopList();
   }

从上面我们可以得知,刚刚进入页面会执行一次 getShopList() 请求,在每一次触底后也会再次加载数据请求,虽然说看上去挺完整的,但是每当我们在测试时频繁的往下滑就会发现,只触一下底居然能执行好几次数据请求,因此得通过下方节流阀来控制数据请求;

节流阀实现

节流阀的实现分为 3 步骤 : 定义开关变量 - 使用开关实现单独请求 - 判断是否为正在请求

首先在 data 中定义一个开关变量 isLoding

   data: {
     ...
     isloading: false // 开关: 用于判断是否正在加载
   },

其次在请求函数中配置 开 与 关,逻辑是执行加载的条件是isLodingfalse ,表示现在没有加载;每当触发上拉触底时,使用 isLodingtrue, 表示正在执行加载;

其中 wx.showLoading()wx.hideLoding() 为加载样式,可根据自身按需使用

 getShopList () {
     // 节流阀 -- 执行加载
     this.setData({
       isLoding : true
     })
     // 加载请求时显示加载样式
     wx.showLoading({
       title: '加载中...',
     })
     wx.request({ ...
       success: () => {... },
       // complete :函数请求结束后才执行
       complete: () => {
         // 结束请求时关闭加载样式
         wx.hideLoading()
         // 节流阀 -- 放行加载
         this.setData({
           isLoding : false
         })
       }
     })
   },

到这里还不够,我们只是让其搭配开关加载,没有达到真正的节流;

因此还需在触发上拉触底时加上一句关键判断,修改后的代码为:

  onReachBottom() {
     if (this.data.page * this.data.pageSize >= this.data.total) { return ... }
     
     // 判断如果正在加载就不执行上拉触底数据请求
     if (this.data.isLoding) return;
                                                             
     this.setData({
       page: this.data.page + 1
     })
     this.getShopList();
   },

这种方式适用于多种场景,不止于小程序,这是一种编程思想 最后如果本文对于本文有疑惑,还请指导勘正 (●'◡'●)