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

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