Vue + better-scroll 入门教程

这几天研究项目时,看到了 better-scroll 插件,看着感觉功能挺强,据称是目前最完善的滚动插件,也就结合着Vue框架学习了起来,自己上手练习总会遇到better-scroll 已经初始化了, 但是没法滚动的情况,回过头看better-scroll的官方文档,找不到答案。感觉其文档还是过于简单, 很多需要举例明确说明的概念都没有讲清楚,和Vue的官方文档相比,确实存在着不小的差距。当然,这里不是说better-scroll插件做的不够好,只是文档有点简略了,对新手不太友好。

 

大家可能已经看过better-scroll的官方文档,下面的这张图片引自官网,其中wrapper(绿色的)为父元素,它会有固定的高度,content(黄色的)是父容器的第一个子元素,它的高度会随着内容的大小而撑高。一旦content的高度超过了父容器的高度,我们就可以实现滚动了,这就是 better-scroll 的滚动原理。

 Vue + 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>

此时,我们将页面运行出来,如下:

Vue + better-scroll 入门教程

结果页面依然无法滚动! 我们来找找原因。

结合代码一起探讨,在我们封装的组件里,我们初始化better-scroll时,针对的父元素是BScroll.vue里的 this.$refs.scrollRef,再回到父组件(CityList.vue),我们将需要滚动的元素放到了<div></div>里,显然符合父元素的第一个子元素。由此,我们可以推断,是另外一个原因,我们需要为 父元素(this.$refs.scrollRef) 指定高度。

添加以下CSS:

 .content-scroll{
    height: 200px;
  }

或者:

 .content-scroll{
    display: absolute; 
  }

此时,我们发现页面已经可以滚动,达到了我们想要的效果!

 

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

原创不易,若文章帮助到您,您也可以打赏,请俺喝个咖啡哦~

上一篇:使用better-scroll在vue中封装自己的Scroll组件


下一篇:使用better-scroll,完成平滑滚动效果