better-scroll遇見vue

  • 介紹better-scroll

better-scroll 最常見的應用場景是列表滾動,我們來看一下它的 html 結構

<div class="wrapper">
  <ul class="content">
    <li>...</li>
    <li>...</li>
    ...
  </ul>
  <!-- 這裏可以放一些其它的 DOM,但不會影響滾動 -->
</div>

上面的代碼中 better-scroll 是作用在外層 wrapper 容器上的,滾動的部分是 content 元素。這裏要注意的是,better-scroll 只處理容器(wrapper)的第一個子元素(content)的滾動,其它的元素都會被忽略。

最簡單的初始化代碼如下:

import BScroll from 'better-scroll'
let wrapper = document.querySelector('.wrapper')
let scroll = new BScroll(wrapper)
  • better-scroll在vue中的使用

安裝 npm install better-scroll --save

<template>
  <div class="wrapper" ref="wrapper">
    <ul class="content">
      <li>...</li>
      <li>...</li>
      ...
    </ul>
  </div>
</template>
<script>
  import BScroll from 'better-scroll'
  export default {
    mounted() {
      this.$nextTick(() => {
        this.scroll = new Bscroll(this.$refs.wrapper, {})
      })
    }
  }
</script>

Vue.js 提供了我們一個獲取 DOM 對象的接口—— vm.$refs。在這裏,我們通過了 this.$refs.wrapper訪問到了這個 DOM 對象,並且我們在 mounted 這個鉤子函數裏,this.$nextTick 的回調函數中初始化 better-scroll 。因爲這個時候,wrapper 的 DOM 已經渲染了,我們可以正確計算它以及它內層 content 的高度,以確保滾動正常。

這裏的 this.$nextTick 是一個異步函數,爲了確保 DOM 已經渲染,感興趣的同學可以瞭解一下它的內部實現細節,底層用到了 MutationObserver 或者是 setTimeout(fn, 0)。其實我們在這裏把 this.$nextTick 替換成 setTimeout(fn, 20) 也是可以的(20 ms 是一個經驗值,每一個 Tick 約爲 17 ms),對用戶體驗而言都是無感知的。

  • better-scroll的事件
<template>
  <div class="wrapper" ref="wrapper">
    <ul class="content">
      <li v-for="item in data">{{item}}</li>
    </ul>
    <div class="loading-wrapper"></div>
  </div>
</template>
<script>
  import BScroll from 'better-scroll'
  export default {
    data() {
      return {
        data: []
      }
    },
    created() {
      this.loadData()
    },
    methods: {
      loadData() {
        requestData().then((res) => {
          this.data = res.data.concat(this.data)
          this.$nextTick(() => {
            if (!this.scroll) {
              this.scroll = new Bscroll(this.$refs.wrapper, {})
              this.scroll.on('touchend', (pos) => {
                // 下拉動作
                if (pos.y > 50) {
                  this.loadData()
                }
              })
            } else {
              this.scroll.refresh()
            }
          })
        })
      }
    }
  }
</script>

這段代碼比之前稍微複雜一些, 當我們在滑動列表鬆開手指時候, better-scroll 會對外派發一個 touchend 事件,我們監聽了這個事件,並且判斷了 pos.y > 50(我們把這個行爲定義成一次下拉的動作)。如果是下拉的話我們會重新請求數據,並且把新的數據和之前的 data 做一次 concat,也就更新了列表的數據,那麼數據的改變就會映射到 DOM 的變化。需要注意的一點,這裏我們對 this.scroll 做了判斷,如果沒有初始化過我們會通過 new BScroll 初始化,並且綁定一些事件,否則我們會調用 this.scroll.refresh 方法重新計算,來確保滾動效果的正常。

官網https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/#better-scroll%20%E6%98%AF%E4%BB%80%E4%B9%88
參考https://zhuanlan.zhihu.com/p/27407024

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章