Pull-down refresh and pull-up loading in WeChat applet

Pull-down refresh and pull-up loading are a very common business requirement. In the WeChat applet, a pull-down refresh method is provided onPullDownRefresh. It is relatively inconvenient to implement pull-up loading.

Pull down to refresh

Although the official WeChat document has many pits, the introduction of pull-down refresh is still very comprehensive. Slightly brought it here.

  • First, the global configin the windowconfiguration enablePullDownRefresh.
  • In the Pagedefinition onPullDownRefreshhook function. After reaching the pull-down refresh condition, the hook function is executed and the request method is initiated.
  • After the request returns, calling wx.stopPullDownRefreshto stop the pull-down refresh.

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)
}复制代码

The effect is as follows: You will find that the pull-down process is a bit stiff. This is actually the reason why the background color is not added. Try again after adding the background color. Feeling better now. Pull-down refresh has ready-made configurations and methods, which are easy to implement, but pull-up loading is different.
image

image

Pull up loading

First look at the effect to be achieved, this is the pull-up loading on the 3g end. The applet must achieve the same effect. First of all, the functions are
image

  • Click back to the top, this is very well implemented, there is a corresponding back to the top function
  • Sliding the screen to record the current page number is also very easy to achieve, mainly to monitor the scroll event, determine the height of the corresponding scroll bar, and calculate the height of it and the child container.
  • Pull up loading animation

There are two implementation schemes here. One is the pagebuilt-in pull-down bottom hook event onReachBottomcan do is to pull down part of the time in the end to inform you hit bottom, is a scroll-viewlabel that comes with the event. Now use two methods to implement pull-up loading.

Pull up bottom event onReachBottom

template

<template>
  <view class="loading"></view>
  <view class="container"  
        @touchmove="moveFn" 
        @touchstart="startFn" 
        @touchend="endFn"
        style="transform:translate3d(0,{
   
   {childTop}}px,0)">
    <repeat for="{
   
   {list}}" 
            key="index" 
            index="index" 
            item="item">
        <view>{
   
   { item }}<text>{
   
   {index}}</text></view>
    </repeat>
    </view>
</template>复制代码

Hook function

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
    })
  }
}复制代码

Take a look at the effect after completion:
image

Rolling container to achieve pull-up loading

scroll-view: scrollable view area.
Its specific usage will not go into details, just look at the official document. Here is a solution to the above-mentioned problems.

  • bindscrolltolowerNative analogy global hook onReachBottom
    template
<scroll-view    scroll-y 
                id="content"   
                @scroll="scroll"  
                @scrolltolower="lower" 
                scroll-top="{
   
   {gotoTopNum}}" 
                lower-threshold="100" 
                style="transform:translate3d(0,{
   
   {childTop}}px,0)">
    <view  class="sty-search" 
            @touchmove="moveContent" 
            @touchstart="startContent" 
            @touchend="endContent">...</view>
</scroll-view>复制代码

The above is the final template, you may be wondering why it is so complicated. Although complicated, each attribute is useful. Of course, there are several pits waiting for us.
First, the nodes are divided into rolling containers and sub-containers.

Q: Why is there a sub-container nested in the scroll container and the three drag methods are bound to it?
A: This is the first pit because the scroll-viewcontainer can not bind touchmoveevent, that what will happen if bound? Not much, the event hook will not be called. (This pit cannot be found in the official documentation. At the time, it was bound and not called. A solution was found in the community, which is to bind the touchmove event to the sub-container)
Let’s look at the code.

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
      }
      /* 这句是解决回到顶部的bug */
      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: Why should touchStarttime be gotoTopNumset undefined?
A: Because there is a return to the top of this page function, when back to the top, gotoTopNumset to 0, the next turn again, although the actual scrollTopchange, but gotoTopNumalso to 0, When you click back to the top again, because the data has not changed, the view layer will not be updated. So touchStartwhen given gotoTopNuman invalid value, click again to return to the top, the view layer also updated.

image

Native scroll OR scroll-view

Compared Native scrolling scroll-view
performance Smooth Too many nodes will obviously freeze
Rolling function onPageScroll bindscroll
back to the top wepy.pageScrollTo(object) has animation effect by default and cannot be cancelled Set node properties scroll-top
Pit Not found yet 1, and enablePullDownRefresh, ReachBottomcannot coexist 2, cannot bind touchmove event 3, cannot trigger double-click the bar to return to the top "Easter egg"

END...Are you...

not at all.

Real machine test

The implemented pull-up loading runs smoothly on the emulator, and there is no problem. but.
If it is a Mac machine (for the time being tested on iphone5 and iPhone7), there is such a problem, the rebound effect of the pull-up or pull-down, this effect will affect the distance of the pull-up.
This problem has been thought about for a long time, but it cannot be solved elegantly at present.
So I asked the product manager to modify the requirements and removed the pull-up animation effect so the final effect became:
image

to sum up

  1. Operating nodes in the WeChat applet is expensive, more expensive than operating in the browser (this is obtained by comparing the smoothness of the pull-up loading function on the 3g side and the WeChat applet), after the release of version 1.4.0 Although many methods are given operation node, such a node to obtain the width and height, or by idgetting a node selector. Please minimize the frequency of calling these methods ( 函数节流) or cache the results
  2. Use your brain before you do it! ! ! Otherwise you will take a lot of detours...

 

Guess you like

Origin blog.csdn.net/weixin_44273311/article/details/106985027
Recommended