评论

极致的scroll-view的下拉刷新扩展组件

scroll-view的下拉刷新扩展组件

不敢说是最好的,但是感觉也应该是性能和体验比较极致的下拉刷新扩展了,老规矩,代码片段放最后了~

  • 2020.2.22 修复了小程序基础库v2.10.2带来的不能滚动的问题,最新代码片段见scroll-view-extends

原理

其实原理很简单,和普通H5以及市面上有的下拉刷新没有特别大的区别,都是基于touch手势检测事件来实现下拉刷新的。touchstart的时候记录当前触摸点,touchmove的时候开始计算移动方向和移动距离, touchend的时候计算是否要进行下拉刷新操作。如图所示:

实现方法

调研了一些实现方法,目前大部分都是通过js计算,然后setData来改变元素的transform值实现下拉刷新。考虑到性能问题,此处使用了wxs的响应式能力来实现整个计算逻辑,不用通过逻辑层和视图层通信,直接在视图层进行渲染。具体文档请参考wxs响应事件

这里在list组件(由scroll-view组成)下抽出了一个scroll.wxs作为响应事件的事件处理函数集合,源码基本上就在scroll.wxslist组件。

scroll.wxs定义了如下变量和函数:

var moveStartPosition = 0     //开始位置
var moveDistance = 0          //移动距离

var moveRefreshDistance = 60  //达到刷新的阈值
var moveMaxDistance = 100     //最大可滑动距离
var isRefreshMaxDown = false  //是否达到了最大距离, 用来判断是否要震动提示

var loading = false           //是否正在loading

... ...

module.exports = {
  touchStart: touchStart, //手指开始触摸事件
  touchMove: touchMove, //手指移动事件
  touchEnd: touchEnd, //手指离开屏幕事件
  loadingTypeChange: loadingTypeChange, //请求状态变化监听,监听刷新请求开始和请求完成
  triggerRefresh: triggerRefresh //主动触发刷新操作,比如点击页面上一个按钮,重新刷新list,这就需要用到这个方法
}
  • touchStarttouchMove就不用说了,代码注释都很明白,普通的监听移动和处理逻辑。

  • touchEnd主要是判断移动距离是否达到了阈值,然后根据结果,调用监听实例的callMethod方法触发refreshStart或者refreshCancel方法,这两个方法都是写到list组件里面的,用来触发刷新方法或者取消刷新。

  • loadingTypeChange方法主要是监听刷新是否完成,以此来触发动画效果。

  • triggerRefresh通过监听主动触发的变量来处理。如果需要主动触发刷新,则调用list组件内部的forceRefresh方法,具体使用示例在index/index/jsonLoad函数有: this.selectComponent('.list').forceRefresh()

  • scroll.wxs里面还有一个未导出的方法,叫drawTransitionY,这个方法主要是因为ios12对于transition动画效果支持的不好,所以自己写了个Y轴方向的动画(linear线性的),大佬们可以自己往上添加各种ease-in-out效果。

里面具体的实现可以查看代码注释哦~

使用

好了,前面讲了实现的原理和方法,那么在代码里面,应该怎么直接使用呢?如下代码所示:

<!-- 使用示例 -->
<list class="list" refresh-loading="{{refreshLoading}}" loading="{{loading}}" bindrefresh="initList" bindloadmore="loadmore">
  <!-- your code -->
</list>
  • refresh-loading属性用来通过外部loading态来控制刷新动画的开始结束,因为每当变化refresh-loading的值时,会将变化同步到组件内的showRefresh属性,wxs通过监听showRefresh来处理动画逻辑。

  • loading属性是上拉加载更多的时候触发的loading态展示,跟刷新无关

  • bindrefresh是刷新触发时绑定的函数,下拉刷新动画成功开始后触发这个函数

  • bindloadmore透传scroll-view的加载更多方法

当然,源码里面也包含了一个list-item组件,这个跟本文没太大关系,是用来做瀑布流长列表内容太多时的内存不足问题解决方案的,具体请看解决小程序渲染复杂长列表,内存不足问题

干货

最后,上代码片段, 小程序代码片段

github地址

最后一次编辑于  2020-02-22  
点赞 10
收藏
评论

15 个评论

  • 174斤的胖狗子
    174斤的胖狗子
    2020-03-11

    wxs和js不能通信是真的头大。。有的时候存在禁止翻页的情况,但wxs又得不到这状态

    2020-03-11
    赞同 1
    回复 1
    • 宗仔GEG
      宗仔GEG
      2020-03-16
      可以通行,不过比较绕
      2020-03-16
      回复
  • 丶
    08-13

    谢谢大佬

    不过最近在真机上出了个问题,就是list组件中调用wxs的方法时,如调用touchEnd,写的是bindtouchEnd,在真机上会报错,虽然是警告类型的错误,但是会导致组件下拉刷新无响应,无法下拉。我把组件里调用wxs的方式改为带冒号的就好了,如bind:touchEnd。

    很奇怪,之前一直没事,今天突然发现无响应了,以前绝对没有这个问题。

    08-13
    赞同
    回复
  • xcode糖糖
    xcode糖糖
    2022-11-04

    怎么修改 list-container 的高度

    2022-11-04
    赞同
    回复
  • 哈罗哈皮
    哈罗哈皮
    2020-08-12

    大佬我想请教下,这个change:prop和prop是view的什么属性?好神奇的属性

    2020-08-12
    赞同
    回复 1
    • 宗仔GEG
      宗仔GEG
      2020-08-15
      是wxs响应事件的独有属性,可以看相关文档
      2020-08-15
      回复
  • 荣
    2020-06-09

    岱宗?

    2020-06-09
    赞同
    回复 1
    • 宗仔GEG
      宗仔GEG
      2020-06-26
      被你发现了,你是?
      2020-06-26
      回复
  • D.💨
    D.💨
    2020-05-29

    有一个小bug,快速上下滚动并触顶,bindscroll事件scrollTop属性 会有概率不为零。造成了下拉刷新无效。(ps:bindscrolltoupper也会有概率不准)

    解决办法:给 scroll-view组件添加 throttle="{{false}}" 可以解决。


    2020-05-29
    赞同
    回复 1
    • 宗仔GEG
      宗仔GEG
      2020-06-26
      6666,可以可以
      2020-06-26
      回复
  • 龙一
    龙一
    2020-05-08

    touchmove 在滚动的时候没触发啊,大佬解决了吗

    2020-05-08
    赞同
    回复 2
    • 宗仔GEG
      宗仔GEG
      2020-06-26
      咦,可以触发啊,能详细说说吗
      2020-06-26
      回复
    • 龙一
      龙一
      2020-06-28回复宗仔GEG
      就是 滚动的时候不触发touchmove,在scrolltop变成0后,就是滚到顶了,或者滚到底了 就会触发了
      2020-06-28
      回复
  • Peter👊
    Peter👊
    2020-04-21

    牛皮

    2020-04-21
    赞同
    回复
  • Object
    Object
    2020-03-25

    微信开发者工具上测试,下拉页面抖动

    2020-03-25
    赞同
    回复 2
    • Peter👊
      Peter👊
      2020-04-21
      抖动问题自己写一个节流就行了
      2020-04-21
      回复
    • 龙一
      龙一
      2020-05-09
      抖动估计是 系统api震动调用吗
      2020-05-09
      回复
  • 青炒的三毛
    青炒的三毛
    2020-03-18

    貌似不支持scrollIntoView啊

    2020-03-18
    赞同
    回复 1
    • 宗仔GEG
      宗仔GEG
      2020-03-18
      嗯嗯,这个可以自行加一些属性扩展就行,后续我会把测试完善的npm包发出来~包含完整的功能
      2020-03-18
      回复

正在加载...

登录 后发表内容