Movable-view實現列表的下拉重新整理上拉載入

上帝遺忘之子發表於2019-02-16

微信小程式自身有下拉重新整理的動態效果,但是這個效果只針對page,如果需要只對其中的某個滾動的子元素做下拉的效果,是沒法實現的,當然還有scroll-view,但是scroll-view在到達頂部和底部的時候比較生硬,沒有回彈的效果,所以我就想有沒有方法能實現這個回彈的效果。

我試了以下三種方法

1.使用better-scroll和mpvue

使用better-scroll外掛,用vue的方式寫滾動列表,實現了簡單的下拉重新整理上拉載入,better-scroll本身就有滾動回彈的效果,寫完之後,在瀏覽器裡看是沒問題了,但是經過mpvue編譯成小程式之後,初始化better-scroll物件的時候直接報錯了,我估計是因為better-scroll有使用到dom物件,但是小程式裡面是沒有dom物件的,具體的原因我沒有深究。

2.使用小程式的movable-view和scroll-view實現列表

使用movable-view,裡面巢狀scroll-view,movable-view和scroll-view的寬高是一樣的,這樣使用的話是可以滾動的,但是在開發者工具裡面沒有回彈的效果,和直接使用scroll-view差不多,手機上倒是有滾動回彈的效果,這樣開發的時候就沒辦法用了。

3.動態計算movable-view的高度

使用movable-view,movable-view裡面只有一個直接子節點,一個普通的view,姑且稱這個view為content,content不給高度,靠裡面的元素來撐高,然後在onReady裡面獲取到content的高度,賦值給movable-view,是的movable-view的高度和content的高度一致,這樣就可以了。上拉載入和下拉重新整理主要是監聽change事件,判斷他的位置,當content的內容改變的時候,再重新獲取一下content的高度賦值給movable-view即可。但是這個還有點問題,就是不能在app.json中使用usingComponents,也不能在頁面的json檔案裡面使用這個屬性,也就是不能使用自定義元件。具體問題還不知道為什麼,可能是微信小程式的一個bug吧,使用了之後page的寬高和movable-view的位置會變得很奇怪。

下面是我的程式碼

<view class=`container`>
  <movable-area class=`area`>
    <movable-view class=`view` style="height: {{h}}px;" direction="vertical" inertia out-of-bounds>
      <view class=`content`>
        <view class=`box` wx:for="{{list}}" wx:key="{{index}}">{{index}}</view>
      </view>
    </movable-view>
  </movable-area>
</view>


page {
  width: 100%;
  height: 100%;
}

.container {
  width: 100%;
  height: 100%;
}

.box {
  width: 100%;
  height: 200rpx;
  background-color: #FFEE00;
}

.area {
  width: 100%;
  height: 100%;
}

.view {
  width: 100%;
}




Page({
  data: {
    isReseting: false //正在回彈
  },
  onLoad: function() {

    let list = [];
    for (let i = 0; i < 10; i++) {
      list.push(i);
    }
    this.setData({
      list
    })
  },
  onReady: function() {
    const query = wx.createSelectorQuery();
    query.select(`.area`).boundingClientRect(res => {
      this.data.areaH = res.height;
    }).exec();
    this.refresh();
  },
  refresh: function() {
    const query = wx.createSelectorQuery();
    query.select(`.content`).boundingClientRect(res => {
      this.setData({
        h: res.height
      });
    }).exec();
  },
  change: function (e) {
    if (e.detail.source === `out-of-bounds`) {

      if (e.detail.y < (this.data.areaH - this.data.h - 10)) {
        //到達下拉重新整理的條件
        if (!this.data.isReseting) {
          //控制在回彈錢不再觸發
          this.data.isReseting = true;
          let list = [];
          for (let i = 10; i < 20; i++) {
            list.push(i);
          }
          this.setData({
            list: this.data.list.concat(list)
          })

          this.refresh();
        }
      } else if (e.detail.y === 0) {
        this.data.isReseting = false;
      }
    }
  }
})


    

相關文章