1. 程式人生 > 實用技巧 >Vue + better-scroll 入門教程

Vue + better-scroll 入門教程

這幾天研究專案時,看到了 better-scroll 外掛,看著感覺功能挺強,據稱是目前最完善的滾動外掛,也就結合著Vue框架學習了起來,自己上手練習總會遇到better-scroll 已經初始化了, 但是沒法滾動的情況,回過頭看better-scroll的官方文件,找不到答案。感覺其文件還是過於簡單, 很多需要舉例明確說明的概念都沒有講清楚,和Vue的官方文件相比,確實存在著不小的差距。當然,這裡不是說better-scroll外掛做的不夠好,只是文件有點簡略了,對新手不太友好。

大家可能已經看過better-scroll的官方文件,下面的這張圖片引自官網,其中wrapper(綠色的)為父元素,它會有固定的高度,

content(黃色的)是父容器的第一個子元素,它的高度會隨著內容的大小而撐高。一旦content的高度超過了父容器的高度,我們就可以實現滾動了,這就是 better-scroll 的滾動原理。

本篇教程結合程式碼例項,主要針對新手常見的better-scroll已經初始化,但依然無法滾動的問題,主要以下有2點原因,會結合著例項給大家講解:

1、better-scroll 只處理容器(wrapper)的第一個子元素(content)的滾動,其它的元素都會被忽略。

2、父元素需要有固定的高度,否則無法滾動。

一、使用方法:

1. 安裝:

npm install better-scroll

2. 初始化:(兩種都可以)

mounted() {
  setTimeout( ()=> {
     this.scroll = new BScroll(this.$refs.wrapper, {})
   }, 20)
},
mounted() {
  this.$nextTick(() => {
    this.scroll = new Bscroll(this.$refs.wrapper, {})
  })
}

這裡的 this.$nextTick和 setTimeout(fn, 20) 都是可以的(20 ms 是一個經驗值,每一個 Tick 約為 17 ms),對使用者體驗而言都是無感知的。

3. 重點:

better-scroll初始化是針對父容器的第一個子元素。 例如:

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

我們進行初始化:

let scroll = new BScroll('.wrapper', {})

此時,.content1中的內容可以實現滾動,而.content2中的內容是不會實現滾動效果的。

也許你會覺得這裡很容易理解,不過在實際的專案中,我們可能會遇到無法滾動的情況,其中的問題很有可能出在這裡,比如:

<div class="wrapper">
  <section v-for="(value, key) in cities" >
    <p class="title">{{key}}</p>
    <div class="city-box" v-for="item in value">
      <p class="city-name">{{item.name}}</p>
    </div>
  </section>
</div>

其中的cities如下,也就是一個簡單的巢狀迴圈。

cities: {
  "A": [{"name": "阿壩"},{"name": "阿克蘇"}, {"name": "阿拉善盟"}, {"name": "阿勒泰"}], 
  "B": [{"name": "北京"}, {"name": "白城"}, {"name": "百色"}, {"name": "白山"}],
  "C": [{"name": "重慶"}, {"name": "常州"}, {"name": "成都"}, {"name": "滄州"}, {"name": "常德"}],
}

此時對.wrapper進行初始化:

let scroll = new BScroll('.wrapper', {})

你會發現頁面依然無法滾動,但是.wrapper是父容器,<section></section>是其第一個子元素,理論上<section></section>中的內容應該可以實現滾動效果才對,那麼原因在哪裡呢?

這裡的問題實際就是出在巢狀迴圈上,可以看到,由於v-for的存在,實際上頁面是渲染出了三個<section></section>,而better-scroll只會對第一個<section></section>中的內容實現滾動,當第一個<section></section>中的內容高度小於父容器的高度時,頁面是不會滾動的,由此可以解決上述問題,可以在<section></section>的外層再加一個<div></duv>,將三個<section></section>都包裹起來即可

二、將better-scroll封裝成Vue元件

1. 新建BScroll.vue(位於:@/components/):

<template>
  <!--滾動元件-->
  <div class="content-scroll" ref="scrollRef">
    <slot></slot>
  </div>
</template>
<script>
  import BScroll from 'better-scroll'
  
  export default {
    mounted() {
      // 確保在 Dom 初始化後才執行滾動方法
      setTimeout(() => {
        this._initScroll();
      }, 20)
    },
    methods: {
      _initScroll() {
        if(!this.$refs.scrollRef) return ;this.scroll = new BScroll(this.$refs.scrollRef, {});
      },
    },
  }
</script>

2. 在父元件中引用,我們將父元件命名為CityList.vue(位於:@/views資料夾下),我們模擬一些城市的名稱,將其顯示出來:

<template>
  <div class="wrapper" ref="wrapper">
    <bet-scroll class="content-scroll">  <!-- 引用上一步封裝的better-scroll元件 -->
      <div>
        <p v-for="item in cities" :key="item.id" class="city-name">
          {{item.name}}
        </p>
      </div>
    </bet-scroll>
  </div>
</template>
<script>
  import BScroll from '@/components/BScroll.vue';

  export default {
    components: { BetScroll: BScroll },
    data() {
      return {
        probeType: 3,
        listenScroll: true,
        cities: [
          {"id": 1,"name": "北京"},
          {"id": 3,"name": "上海"},
          {"id": 47,"name": "杭州"},
          ...
        ]
      }
    },
  }
</script>
<style>
  .wrapper{
    position: absolute;
    overflow: hidden;   /* 隱藏滾動條 */ 
    left:0;
    right:0;
    top:19vw;
    bottom: 0
  }
  
  .city-name{
    height: 30px;
    border-bottom: 1px solid #f2f2f2;
    line-height: 20px;
  }
</style>

此時,我們將頁面執行出來,如下:

結果頁面依然無法滾動! 我們來找找原因。

結合程式碼一起探討,在我們封裝的元件裡,我們初始化better-scroll時,針對的父元素是BScroll.vue裡的 this.$refs.scrollRef,再回到父元件(CityList.vue),我們將需要滾動的元素放到了<div></div>裡,顯然符合父元素的第一個子元素。由此,我們可以推斷,是另外一個原因,我們需要為 父元素(this.$refs.scrollRef) 指定高度。

新增以下CSS:

 .content-scroll{
    height: 200px;
  }

或者:

 .content-scroll{
    display: absolute; 
  }

此時,我們發現頁面已經可以滾動,達到了我們想要的效果!

若文章中有不正確的地方,歡迎大家交流指正。

原創不易,若文章幫助到您,您也可以打賞,請俺喝個咖啡哦~