栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

浅谈微信小程序中的下拉刷新和上拉加载

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

浅谈微信小程序中的下拉刷新和上拉加载

下拉刷新和上拉加载是业务上一个很常见的需求,在微信小程序里,提供了下拉刷新的方法 onPullDownRefresh 。而实现上拉加载相对来说就比较不方便了。

下拉刷新
  • 虽然微信的官方文档有很多坑,但下拉刷新介绍的还是很全面的。在这里稍稍带过。

  • 首先在全局 config 中的 window 配置 enablePullDownRefresh .在 Page 中定义 onPullDownRefresh 钩子函数。到达下拉刷新条件后,该钩子函数执行,发起请求方法。

  • 请求返回后,调用 wx.stopPullDownRefresh 停止下拉刷新。
config
config = {
    pages: [
      'pages/index'
    ],
    window: {
      backgroundTextStyle: 'light',
      navigationBarBackgroundColor: '#ccc',
      navigationBarTitleText: 'WeChat',
      navigationBarTextStyle: '#000',
      enablePullDownRefresh: true
    }
  }
page
onPullDownRefresh() {
  wepy.showNavigationBarLoading() 
  setTimeout(()=>{
    this.getData = '数据拿到了'
    wepy.stopPullDownRefresh()
    wepy.hideNavigationBarLoading()
    this.$apply()
  },3000)
}

效果如下:

你会发现下拉的过程有些僵硬。这实际上是没有添加背景色的原因,加上背景色后再试试。

现在感觉好多了吧。下拉刷新有现成的配置和方法,很容易实现,可上拉加载就不同了。

上拉加载

首先看一下要实现的效果,这是3g端的上拉加载。小程序要实现同样的效果。

首先功能有

  • 点击回到顶部 这个很好实现,有对应的回到顶部函数

  • 滑动屏幕记录当前页数 这个也很好实现,主要是监听滚动事件,判断对应滚动条高度,去计算其与子容器的高度即可。
  • 上拉加载动画

这里有两个实现的方案。一个是 page 自带的下拉触底钩子事件 onReachBottom 能做的只是下拉到底部的时候通知你触底了,一个是 scroll-view 标签自带事件。现在用两个方法分别实现一下上拉加载。

上拉触底事件 onReachBottom 模板
钩子函数
data = {
  getdata: '',
  top: 0,
  lastTop: 0,
  canDrag: false,
  list: []
}
onReachBottom() {
 this.canDrag = true
}
methods = {
  moveFn(ev) {
    let nowY = ev.changedTouches[0].clientY
    nowY = nowY-this.lastTop
    if(nowY > 0 )
      this.canDrag = false
    if( nowY<=0 && this.canDrag ) {
      this.top = nowY
    }
    if( -this.top>= this.maxTop  )
      this.top = -this.maxTop
  },
  startFn(ev) {
    this.lastTop = ev.changedTouches[0].clientY 
  },
  endFn() {
    if(this.top <= -this.maxTop) {
      this.text = "去请求数据了"
      setTimeout(()=>{
 this.text = "请求回来了"
 this.canDrag = false
 this.list.push(...["数据","数据","数据"])
 this.$apply()
 this.top = 0;
 return
      },1000)
    }
  },
  gotoTop() {
    wepy.pageScrollTo({
      scrollTop: 0
    })
  }
}

完成后看一下效果:

滚动容器实现上拉加载

scroll-view: 可滚动视图区域。
它的具体用法不赘述,看官方文档就行了。这里提解决上述问题的方法即可。

  • bindscrolltolower 类比原生全局钩子 onReachBottom
模板

    ...

以上就是最终的模板,你可能在想为什么这么复杂。虽然复杂,但每个属性都是有用的,当然这其中有几个坑在等着我们。
首先节点分为滚动容器和子容器。

Q:为什么滚动容器里嵌套一个子容器,并且将拖动的三个方法绑定在它上面。

A:这是第一个坑,因为 scroll-view 容器不能绑定 touchmove 事件,那如果绑定了会怎么样呢?不会怎么样,事件钩子不会调用。(这个坑在官方文档查不出来,当时绑定了不调用,在社区找到了解决方法,就是将touchmove事件绑定到子容器)
再来看代码

methods = {
    async lower() {
      this.canDrag = true
    },
    scroll (ev) {
      this.scrollTop = ev.detail.scrollTop
      if (ev.detail.deltaY > 0) {
 this.canDrag = false
      }
      let nowSet = this.documentHeight+this.scrollTop-this.contentHeader
      let num = Math.ceil(nowSet/this.listHeight) - 1
      num = Math.floor(num / this.pageBean.pageSize) + 1
      num = (num > this.pageBean.pageNo) ? this.pageBean.pageNo : num 
      if(num != this.page) {
 this.page = num
 this.$apply()
      }
    },
    startContent(ev) {
      this.lastTop = ev.changedTouches[0].clientY
      if(!this.documentHeight){
 this.documentHeight = wx.getSystemInfoSync().windowHeight
      }
      
      if (this.gotoTopNum || this.gotoTopNum==0) { this.gotoTopNum = undefined }
    },
    moveContent (ev) {
      let {
 pageNo,
 pageSize,
 totalCount
      } = this.pageBean
      let nowY = ev.changedTouches[0].clientY
      nowY = nowY-this.lastTop
      if (this.canDrag && nowY) {
   this.state = 1;
   if (nowY <= -this.maxMove) {
     nowY = -this.maxMove
   }
   if (nowY <= 0) {
     this.childTop = nowY
   } 
      }
    },
    async endContent(ev) {
      let {
 pageNo,
 pageSize,
 totalCount
      } = this.pageBean

      if (this.childTop === -this.maxMove) {

 
 if (pageNo >= this.maxPage || pageNo * pageSize >= totalCount) {
     this.state = 0
 } else {
   this.pageBean.pageNo++ 
   await this.fillData()
   this.childTop = 0
   this.canDrag = false
   this.$apply()
 }
      }
      
      this.childTop = 0
    },
    gotoTop() {
      this.gotoTopNum = 0
    },
}

Q: 为什么要在 touchStart 的时候 将 gotoTopNum 置为 undefined?

A: 因为这个页面有一个回到顶部的功能,当回到顶部时,gotoTopNum 置为0,再次下翻时,虽然实际的 scrollTop 改变了,但是 gotoTopNum 还为0,再次点击回到顶部时,因为数据未改变,视图层就不会去更新。所以在 touchStart 的时候给 gotoTopNum 一个无效的值,再次点击回到顶部时,视图层也就更新了。

原生滚动 OR scroll-view

END...了吗......

并没有。

真机测试

实现的上拉加载在模拟器上跑的很流畅,不存在问题。可是。
如果是苹果机的话(暂时测试iphone5 和 iPhone7),存在这样一个问题,上拉或下拉回弹效果,这个效果会影响上拉的距离。
这个问题想了很久,目前不能优雅的解决。
所以就找产品经理修改了需求,去掉了上拉动画效果 所以最终的效果就变成:

总结
  1. 在微信小程序里操作节点是昂贵的,比在浏览器里操作还昂贵(这是通过比较上拉加载功能在3g端和微信小程序的流畅度得来的),在 1.4.0版本发布之后,虽然给出了很多操作节点的方法,比如得到一个节点的宽高、或者通过 id 选择器得到一个节点。请尽量减少这些方法的调用频率(函数节流 )或 缓存结果
  2. 动手之前先动脑!!!不然会走很多弯路...

作者:丁香园F2E,原文地址

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/245370.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号