关于专题【vue开发音乐App】

开发页面时,如果想让某个区域支持滚动(或者需要监听滚动事件),一般会使用better-scroll——一款重点解决移动端(已支持 PC)各种滚动场景需求的插件,作者依然是黄轶老师,具体使用方法和例子可查看官方文档

学习《Vue.js高仿饿了么 》 时第一次接触better-scroll ,在使用该插件的过程中,发现实现步骤、逻辑基本一致,如果能固化这些步骤抽象成自定义组件( scroll.vue,类似于微信小程序的scroll-view组件 ),日后再有类似的滚动需求,直接调用<scroll></scroll>即可,这样也使代码更简洁高效且易于维护。

首先需要安装better-scroll,执行命令:cnpm i better-scroll -S

一、 src/base/scroll/scroll.vue

<template>
  <!--这部分的代码很简单(模板代码越简单说明组件使用越灵活),最外层是一个包裹层,中间一个插槽slot,意味着将来需要滚动的元素会放在该插槽的位置,值得注意的是,对于插入slot的多个子元素,只有第一个子元素可以滚动-->
  <div ref="wrapper">
    <slot></slot>
  </div>
</template>

<script type="text/ecmascript-6">
  import BScroll from 'better-scroll'

  export default {
    name: 'scroll',
    props: {
      // 有时候我们需要知道滚动的位置。
      // 1:会非实时(屏幕滑动超过一定时间后)派发scroll事件;2:会在屏幕滑动的过程中实时的派发scroll事件;3:不仅在屏幕滑动的过程中,而且在momentum滚动动画运行过程中实时派发scroll事件;不设置则默认为0,即不派发scroll事件。
      probeType: {
        type: Number,
        default: 1
      },
      // 是否手动派发点击事件,better-scroll默认会阻止浏览器的原生click事件。
      // true:better-scroll会派发一个click事件。
      click: {
        type: Boolean,
        default: true
      },
      // 是否监听滚动
      listenScroll: {
        type: Boolean,
        default: false
      },
      // 用于滚动的列表数据
      data: {
        type: Array,
        default: null
      },
      // 滚动前的钩子
      beforeScroll: {
        type: Boolean,
        default: false
      },
      // 刷新前的延迟时间,单位:毫秒
      refreshDelay: {
        type: Number,
        default: 20
      }
    },
    // 在mounted钩子中初始化scroll
    mounted () {
      // 延迟20毫秒是用于抵消浏览器的刷新耗时(一般17毫秒),确保DOM已经渲染
      setTimeout(() => {
        this._initScroll()
      }, 20)
    },
    methods: {
      _initScroll () {
        if (!this.$refs.wrapper) {
          return
        }
        // 初始化better-scroll
        this.scroll = new BScroll(this.$refs.wrapper, {
          probeType: this.probeType,
          click: this.click
        })
        // 如果需要监听滚动,则向上派发scroll事件
        if (this.listenScroll) {
          let that = this
          this.scroll.on('scroll', (pos) => {
            that.$emit('scroll', pos)
          })
        }
        if (this.beforeScroll) {
          this.scroll.on('beforeScrollStart', () => {
            this.$emit('beforeScroll')
          })
        }
      },
      // 以下是对一些better-scroll方法的代理
      disable () {
        this.scroll && this.scroll.disable()
      },
      enable () {
        this.scroll && this.scroll.enable()
      },
      refresh () {
        this.scroll && this.scroll.refresh()
      },
      scrollTo () {
        this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments)
      },
      scrollToElement () {
        this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments)
      }
    },
    // 设置一个监听器,如果data发生变化,就需要重新计算scroll的高度,即调用refresh()方法
    watch: {
      data () {
        setTimeout(() => {
          this.refresh()
        }, this.refreshDelay)
      }
    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>

二、使用方法

<scroll :data="list" :listen-scroll="true" @scroll="scroll">

  <!--只要第一个元素才会滚动-->
  <ul>
    <li v-for="item in list">
      ...
    </li>
  </ul>

  <!--以下元素不会滚动-->
  <div class="a"></div>
  <div class="b"></div>
  <div class="c"></div>

</scroll> 

三、常见问题及处理

  • 如果better-scroll不能滚动,可能是因为滚动元素的DOM未渲染成功,better-scroll计算不了滚动元素的高度,从而失效;
  • 如果滚动数据或DOM发生变化,一定要执行better-scroll的refresh;
  • 当better-scroll和fastclick在点击事件上有冲突,可以为目标元素添加fastclick提供的“needsclick”样式类解决。

1+
浏览:1,189

0 条评论

发表评论

电子邮件地址不会被公开。

你必须允许浏览器启用JavaScript才能看到验证码

Scroll Up