better-scroll 移动端滚动

2022-08-02,

文章目录

  • 简介
  • better-scroll 1.x
    • 安装
    • 起步
    • 配置参数
      • probeType 侦测滚动到的位置
      • click 监听按钮点击
      • pullUpLoad 上拉加载
    • 方法
      • on() 监听当前实例上的事件
      • finishPullUp() 上拉加载完成
      • refresh() DOM改变后需要刷新 better-scroll
      • scrollTo() 滚动到指定的位置
    • 事件钩子
  • BScroll 1.x 与Vue结合
    • 异步数据的处理
    • 数据的动态更新
    • 路由跳转时记录离开时状态和位置
  • BetterScroll 2.x

简介

better-scroll 是基于原生 JS 实现的,不依赖任何框架。它编译后的代码大小是 63kb,压缩后是 35kb,gzip 后仅有 9kb,是一款非常轻量的 JS lib。

无法滚动问题

better-scroll 只处理绑定容器(wrapper)的第一个子元素(content)的滚动,其它的元素都会被忽略。

better-scroll 1.x

安装

npm install better-scroll --save

import BScroll from 'better-scroll'

起步

  • content如果高度大于浏览器的高度,浏览器会添加默认的滚动效果.
  • wrapper添加overflow: hidden; height: xxxpx;样式将content超过wrapper高度的内容隐藏掉.
<div class="wrapper">
  <ul class="content">
    <li>...</li>
    <li>...</li>
    ...
  </ul>
  <!-- 这里可以放一些其它的 DOM,但不会影响滚动 -->
</div>

import BScroll from 'better-scroll'

let wrapper = document.querySelector('.wrapper')
let scroll = new BScroll(wrapper)

// 当传入一个字符串时,better-scroll 内部会尝试调用 querySelector 去获取这个 DOM 对象
let scroll = new BScroll('.wrapper')

注意:better-scroll 只处理容器(wrapper)的第一个子元素(content)的滚动,其它的元素都会被忽略。

配置参数

better-scroll 支持很多参数配置,可以在初始化的时候传入第二个参数,比如:实现一个纵向可点击的滚动效果

let scroll = new BScroll('.wrapper',{
    scrollY: true,
    click: true
})

better-scroll 支持的参数非常多,可以修改它们去实现更多的 feature(功能)。有些参数better-scroll 已经为你实现了最佳效果可以不进行修改

probeType 侦测滚动到的位置

  • 类型:Number
  • 默认值:0
  • 可选值:1、2、3
  • 作用
    • 0:不侦测实时的位置
    • 1:会非实时(屏幕滑动超过一定时间后)派发scroll 事件,侦测实时位置
    • 2: 在手指滚动的过程中侦测,派发scroll 事件. 手指离开后的惯性滚动过程中不侦测.
    • 3: 只要是滚动, 都侦测.派发scroll 事件

click 监听按钮点击

  • 类型:Boolean
  • 默认值:false
  • 作用:better-scroll 默认会阻止浏览器的原生 click 事件。当设置为 true,better-scroll 会派发一个 click 事件,我们会给派发的 event 参数加一个私有属性 _constructed,值为 true。

pullUpLoad 上拉加载

  • 类型:Boolean | Object
  • 默认值:false
  • 作用:这个配置用于做上拉加载功能,默认为 false。当设置为 true 或者是一个 Object 的时候,可以开启上拉加载.会触发pullingUp事件
pullUpLoad: {
  threshold: 50
}

当距离滚动到底部小于 threshold 值时,触发一次 pullingUp 上拉加载事件。当上拉加载数据加载完毕后,需要执行 finishPullUp 方法,才能继续触发pullingUp事件。

方法

better-scroll 提供了很多灵活的 API,当我们基于 better-scroll 去实现一些 feature 的时候,会用到这些 API.

on() 监听当前实例上的事件

  • 参数:
    • {String} type 事件名
    • {Function} fn 回调函数
import BScroll from 'better-scroll'
let scroll = new BScroll('.wrapper')
function onScroll(pos) {
  console.log(`Now position is x: ${pos.x}, y: ${pos.y}`)
}
// 监听滑动
scroll.on('scroll', onScroll)

finishPullUp() 上拉加载完成

  • 参数:无
  • 返回值:无
  • 作用:当上拉加载数据加载完毕后,需要调用此方法告诉 better-scroll 数据已加载。之后才能继续执行上拉加载事件.

refresh() DOM改变后需要刷新 better-scroll

  • 参数:无
  • 返回值:无
  • 作用:重新计算 better-scroll,当 DOM 结构发生变化的时候务必要调用确保滚动的效果正常。

scrollTo() 滚动到指定的位置

  • {Number} x 横轴坐标(单位 px)
  • {Number} y 纵轴坐标(单位 px)
  • {Number} time 滚动动画执行的时长(单位 ms)

事件钩子

  • scroll: 滑动事件
    • 滚动过程中{Object} {x, y} 滚动的实时坐标
  • pullingUp: 上拉加载
    • 触发时机:在一次上拉加载的动作后,这个时机一般用来去后端请求数据。
  • pullingDown: 下拉刷新
    • 触发时机:在一次下拉刷新的动作后,这个时机一般用来去后端请求数据。

BScroll 1.x 与Vue结合

当 better-scroll 遇见 Vue

  • 可通过vm.$refs选择绑定滚动效果的DOM对象,防止定义了多个同名的class产生冲突
  • 在mounted()钩子函数中绑定,因为这时wrapper 的 DOM 已经渲染了
  • this.$nextTick 是一个异步函数,更新循环结束之后执行延迟回调,获取更新后的 DOM。
<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>

异步数据的处理

<template>
  <div class="wrapper" ref="wrapper">
    <ul class="content">
      <li v-for="item in data">{{item}}</li>
    </ul>
  </div>
</template>
<script>
  import BScroll from 'better-scroll'
  export default {
    data() {
      return {
        data: []
      }
    },
    created() {
      requestData().then((res) => {
        this.data = res.data
        this.$nextTick(() => {
          this.scroll = new Bscroll(this.$refs.wrapper, {})
        })
      })
    }
  }
</script>

为什么这里在 created 这个钩子函数里请求数据而不是放到 mounted 的钩子函数里?因为 requestData 是发送一个网络请求,这是一个异步过程,当拿到响应数据的时候,Vue 的 DOM 早就已经渲染好了,但是数据改变 —> DOM 重新渲染仍然是一个异步过程,所以即使在我们拿到数据后,也要异步初始化 better-scroll。

数据的动态更新

数据改变导致DOM改变后一定要及时使用refresh(),否则可能滚动会出bug.

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

路由跳转时记录离开时状态和位置

  • 使用 <keep-alive> 包裹 <router-view/>
  • 离开时通过 deactivated()钩子函数将当前滚动距离保存在data中
  • 返回时通过activated()钩子函数执行scrollTo()方法滑动到保存的位置,并refresh()刷新

BetterScroll 2.x

BetterScroll 2.x文档 BetterScroll 2.X 里面,我们将 1.X 耦合的 feature 拆分至插件,以达到按需加载、减少包体积的目的。

本文地址:https://blog.csdn.net/lixiaolian123/article/details/107386193

《better-scroll 移动端滚动.doc》

下载本文的Word格式文档,以方便收藏与打印。