vue中使用BetterScroll(网上)

原文链接

BetterScroll 是一款重点解决移动端各种滚动场景需求的开源插件(GitHub地址),有下列功能支持滚动列表,下拉刷新,上拉刷新,轮播图,slider等功能。
为了满足这些功能,better-scroll通过使用惯性滚动、边界回弹、滚动条淡入淡出来确保滚动的流畅。同时还支持很多API和事件,具体支持的事件可以查看官网讲的非常详细。
由于它基于原生JavaScript 实现,不依赖任何框架,所以既可以原生 JavaScript 引用,也可以与目前前端 MVVM 框架结合使用,比如,其官网上的示例就是与 Vue 的结合。

如何使用:

再讲如何使用的之前,我们先来了解一下他的滚动原理:在浏览器中的滚动中,当内容的高度高于外边容器的高度的时候也就出现了滚动条,我们可以通过使用滚动条来看到超出的部分.

better-scroll的原理正是基于这里,内容部分的宽度/高度必须大于外部宽度/高度。所以在使用
的时候外部容器的需要设置固定宽度,还有一个问题需要设置overflow:hidden,这是因为为了隐藏超出部分。然后就是什么时候对better-scroll进行初始化,这个有点麻烦,但是所幸,作者已经在vue框架下进行封装,我们只需要像个麻瓜一样往里边填东西就行了。但是有一点需要注意:滚动的元素只能是第一个容器的第一个元素。源码如下:

  // this.scroller就是滚动的内容,this.wrapper是容器
    this.scroller = this.wrapper.children[0]

如果我们需要滚动多个内容怎么办呢,就用一个元素将其包裹住,让他成为容器的第一个子元素就行了。

让滚动更流畅

在移动端,如果你使用过 overflow: scroll 生成一个滚动容器,会发现它的滚动是比较卡顿,呆滞的。为什么会出现这种情况呢?

因为我们早已习惯了目前的主流操作系统和浏览器视窗的滚动体验,比如滚动到边缘会有回弹,手指停止滑动以后还会按惯性继续滚动一会,手指快速滑动时页面也会快速滚动。而这种原生滚动容器却没有,就会让人感到卡顿。

BetterScroll 的滚动体验

试一试 BetterScroll 的滚动体验吧。体验地址

可以发现,在增加惯性滚动,边缘回弹等效果之后,明显流畅、舒服了很多。那么,这些效果是怎么实现的呢?

惯性滚动

BetterScroll 在用户滑动操作结束时,还会继续惯性滚动一段。首先看一下源码中的 BScroll.prototype._end 函数,这是 touchend、mouseup、touchcancel、mousecancel 事件的处理函数,也就是用户滚动操作结束时的逻辑。

BScroll.prototype._end = function (e) {
    ...
    if (this.options.momentum && duration < this.options.momentumLimitTime && (absDistY > this.options.momentumLimitDistance || absDistX > this.options.momentumLimitDistance)) {
      let momentumX = this.hasHorizontalScroll ? momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options)
        : {destination: newX, duration: 0}
      let momentumY = this.hasVerticalScroll ? momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options)
        : {destination: newY, duration: 0}
      newX = momentumX.destination
      newY = momentumY.destination
      time = Math.max(momentumX.duration, momentumY.duration)
      this.isInTransition = 1
    }
    ...
}

以上代码的作用是,在用户滑动操作结束时,如果需要开启了惯性滚动,用 momentum 函数计算惯性滚动距离和时间。该函数,根据用户滑动操作的速度和 deceleration选项 ——惯性减速来计算滚动距离,至于滚动时间,也是一个可配置的选项。

function momentum(current, start, time, lowerMargin, wrapperSize, options) {
  ...
  let distance = current - start
  let speed = Math.abs(distance) / time
  ...
  let duration = swipeTime
  let destination = current + speed / deceleration * (distance < 0 ? -1 : 1)
  ...
}

边缘回弹

超过边缘时的回弹,有两个处理步骤,第一步是滚动到超过边界时速度要变慢,第二步是回弹到边界。其中,第一步是在源码的 BScroll.prototype._move 函数,这是 touchmove 和 mousemove 事件的处理函数,也就是在用户滑动操作过程中的逻辑。

// Slow down or stop if outside of the boundaries
if (newY > 0 || newY < this.maxScrollY) {
    if (this.options.bounce) {
        newY = this.y + deltaY / 3
    } else {
        newY = newY > 0 ? 0 : this.maxScrollY
    }
}

第二步是调用 BScroll.prototype.resetPosition 函数,回弹到边界。

BScroll.prototype.resetPosition = function (time = 0, easeing = ease.bounce) {
    ...
    let y = this.y
    if (!this.hasVerticalScroll || y > 0) {
      y = 0
    } else if (y < this.maxScrollY) {
      y = this.maxScrollY
    }
    ...
    this.scrollTo(x, y, time, easeing)
    ...
  }

流畅的滚动仅仅是基础,BetterScoll 真正的能力在于:提供了大量通用 / 定制的option 选项 、API 方法和事件,让各种滚动需求实现起来更高效。

如何应用于各种需求场景

下面,以结合 Vue 的使用为例,说一下 BetterScroll 在各种场景下的姿势。

普通滚动列表

比如,有如下列表:

  • {{item}}

我们想要让它垂直滚动,只需要对该容器进行简单的初始化。

import BScroll from ‘better-scroll‘

const options = {
  scrollY: true // 因为scrollY默认为true,其实可以省略
}

this.scroll = new BScroll(this.$refs.wrapper, options)

对于 Vue 中使用 BetterScroll,有一个需要注意的点是,因为在 Vue 模板中列表渲染还没完成时,是没有生成列表 DOM 元素的,所以需要在确保列表渲染完成以后,才能创建 BScroll 实例,因此在 Vue 中,初始化 BScroll 的最佳时机是 mouted 的 nextTick。

// 在 Vue 中,保证列表渲染完成时,初始化 BScroll
mounted() {
   setTimeout(() => {
     this.scroll = new BScroll(this.$refs.wrapper, options)
   }, 20)
},

初始化之后,这个 wrapper 容器就能够优雅地滚动了,并且可以通过 BScroll 实例 this.scroll 使用其提供的 API 方法和事件。

下面介绍几个常用的选项、方法和事件。

滚动条

scrollbar 选项,用来配置滚动条,默认为 false。当设置为 true 或者是一个 Object,开启滚动条。还可以通过 fade 属性,配置滚动条是随着滚动操作淡入淡出,还是一直显示。

// fade 默认为 true,滚动条淡入淡出
options.scrollbar = true

// 滚动条一直显示
options.scrollbar = {
  fade: false
}

this.scroll = new BScroll(this.$refs.wrapper, options)

具体效果可见普通滚动列表-示例。

下拉刷新

pullDownRefresh 选项,用来配置下拉刷新功能。当设置为 true 或者是一个 Object 的时候,开启下拉刷新,可以配置顶部下拉的距离(threshold)来决定刷新时机,以及回弹停留的距离(stop)

options.pullDownRefresh = {
  threshold: 50, // 当下拉到超过顶部 50px 时,触发 pullingDown 事件
  stop: 20 // 刷新数据的过程中,回弹停留在距离顶部还有 20px 的位置
}

this.scroll = new BScroll(this.$refs.wrapper, options)

监听 pullingDown 事件,刷新数据。并在刷新数据完成之后,调用 finishPullDown() 方法,回弹到顶部边界

this.scroll.on(‘pullingDown‘, () => {
  // 刷新数据的过程中,回弹停留在距离顶部还有20px的位置
  RefreshData()
    .then((newData) => {
      this.data = newData
      // 在刷新数据完成之后,调用 finishPullDown 方法,回弹到顶部
      this.scroll.finishPullDown()
  })
})

具体效果可见普通滚动列表-示例。

上拉加载

pullUpLoad 选项,用来配置上拉加载功能。当设置为 true 或者是一个 Object 的时候,可以开启上拉加载,可以配置离底部距离阈值(threshold)来决定开始加载的时机

options.pullUpLoad = {
  threshold: -20 // 在上拉到超过底部 20px 时,触发 pullingUp 事件
}

this.scroll = new BScroll(this.$refs.wrapper, options)

监听 pullingUp 事件,加载新数据。

this.scroll.on(‘pullingDown‘, () => {
  loadData()
    .then((newData) => {
      this.data.push(newData)
  })
})

具体效果可见普通滚动列表-示例。

选择器

wheel 选项,用于开启并配置选择器。可配置选择器当前选择的索引(selectedIndex),列表的弯曲弧度(rotate),以及切换选择项的调整时间(adjustTime)。

options.wheel = {
  selectedIndex: 0,
  rotate: 25,
  adjustTime: 400
}

// 初始化选择器的每一列
this.wheels[i] = new BScroll(wheelWrapper.children[i], options)

具体效果可见选择器 - 示例。

其中联动选择器,需要监听每个选择列表的选择,来改变其他选择列表。

data() {
   return {
     tempIndex: [0, 0, 0]
   }
},
...
// 监听每个选择列表的选择
this.wheels[i].on(‘scrollEnd‘, () => {
  this.tempIndex.splice(i, 1, this.wheels[i].getSelectedIndex())
})
...
// 根据当前选择项,确定其他选择列表的内容
computed: {
  linkageData() {
    const provinces = provinceList
    const cities = cityList[provinces[this.tempIndex[0]].value]
    const areas = areaList[cities[this.tempIndex[1]].value]

    return [provinces, cities, areas]
  }
},

具体效果可见选择器 - 示例中的联动选择器。

轮播图

snap 选项,用于开启并配置轮播图。可配置轮播图是否循环播放(loop),每页的宽度(stepX)和高度(stepY),切换阈值(threshold),以及切换速度(speed)。

options = {
  scrollX: true,
  snap: {
    loop: true, // 开启循环播放
    stepX: 200, // 每页宽度为 200px
    stepY: 100, // 每页高度为 100px
    threshold: 0.3, // 滚动距离超过宽度/高度的 30% 时切换图片
    speed: 400 // 切换动画时长 400ms
  }
}

this.slide = BScroll(this.$refs.slide, options)

具体效果可见轮播图 - 示例。

特殊场景

除了普通滚动列表、选择器、轮播图等基础滚动场景,还可以利用 BetterScroll 提供的能力,做一些特殊场景。

索引列表

索引列表,首先需要在滚动过程中实时监听滚动到哪个索引的区域了,来更新当前索引。在这种场景下,我们可以使用 probeType 选项,当此选项设置为 3 时,会在整个滚动过程中实时派发 scroll 事件。从而获取滚动过程中的位置。

options.probeType = 3
this.scroll = new BScroll(this.$refs.wrapper, options)

this.scroll.on(‘scroll‘, (pos) => {
  const y = pos.y

  for (let i = 0; i < listHeight.length - 1; i++) {
    let height1 = listHeight[i]
    let height2 = listHeight[i + 1]
    if (-y >= height1 && -y < height2) {
      this.currentIndex = i
    }
  }
})

当点击索引时,使用 scrollToElement()方法 滚动到该索引区域。

scrollTo(index) {
  this.$refs.indexList.scrollToElement(this.$refs.listGroup[index], 0)
}

具体效果可见索引列表 - 示例。

开屏引导

开屏引导,其实就是一种不自动循环播放的横向滚动轮播图而已。

options = {
  scrollX: true,
  snap: {
    loop: false
  }
}

this.slide = BScroll(this.$refs.slide, options)

具体效果可见开屏引导 - 示例。因为此需求场景一般只有移动端才有,所以最好在手机模式下看效果。

自由滚动

freeScroll 选项,用于开启自由滚动,允许横向和纵向同时滚动,而不限制在某个方向。

options.freeScroll = true

另外需要注意的是,此选项在eventPassthrough 设置了保持原生滚动时无效。

具体效果可见自由滚动-示例。

小结

BetterScroll 可以用于几乎所有滚动场景,本文仅介绍了在一些典型场景下的使用姿势。

作为一款旨在解决移动端滚动需求的插件,BetterScroll 开放的众多选项、方法和事件,其实,就是提供了一种让我们更加快捷、灵活、精准时机地处理滚动的能力。

作者:滴滴webapp架构组-付楠。
原文链接:http://www.tuicool.com/articles/UJvIjmJ

原文地址:https://www.cnblogs.com/liangru/p/9154808.html

时间: 2024-10-13 02:10:23

vue中使用BetterScroll(网上)的相关文章

Vue中的better-scroll插件

Vue中的better-scroll插件 在需要的文件中添加 import BScorll from 'better-scroll'; 引用的示例代码: let scroll = new BScroll(Dom对象, {//options startX: 0, startY: 0 }) Vue获得Dom对象方法, <div v-el:food-wrapper></div>//定义对象 this.$els.foodWrapper//获取对象 (Vue 更新数据时是异步的,所以在数据未

vue中使用better-scroll实现滑动效果

1.安装:npm install better-scroll 2.引入:import BetterScrol from "better-scroll"; 1.滚动效果 better-scroll在使用的时候需要在dom元素渲染完成之后初始化better-scroll的实例,初始化的时候,先要获取需要滑动的元素,然后在初始化的时候将获取到的元素传递给初始化函数,此时便可实现滑动效果 2.左右联动效果 左右联动效果的实现,是better-scroll通过监听事件实现的. 首先获取到右边内容

better-scroll在vue中的坑

在我们日常的移动端项目开发中,处理滚动列表是再常见不过的需求了,以滴滴为例,可以是这样竖向滚动的列表,如图所示: 也可以是横向滚动的导航栏,如图所示: 可以打开"微信 -> 钱包->滴滴出行"体验效果. 我们在实现这类滚动功能的时候,会用到我写的第三方库,better-scroll. 什么是 better-scroll better-scroll 是一个移动端滚动的解决方案,它是基于 iscroll 的重写,它和 iscroll 的主要区别在这里.better-scroll

better-scroll在vue中的应用

在我们日常的移动端项目开发中,处理滚动列表是再常见不过的需求了,以滴滴为例,可以是这样竖向滚动的列表,如图所示: 微信 -> 钱包->滴滴出行"体验效果. 什么是 better-scroll better-scroll 是一个移动端滚动的解决方案,它是基于 iscroll 的重写,它和 iscroll 的主要区别在 这里 .better-scroll 也很强大,不仅可以做普通的滚动列表,还可以做轮播图.picker 等等. 不少同学可能用过 better-scroll,我收到反馈最多

better-scroll在vue中的使用

一.介绍 关于better-scroll的原文详细介绍请参考,这里只做总结 黄老师的文章<当 better-scroll 遇见 Vue>的详细介绍 better-scroll的api:点击 better-scroll的滚动原理 <div class="wrapper"> <ul class="content"> <li>...</li> <li>...</li> ... </u

vue中监听window.resize的变化

我只想说每个人遇到的bug真的不能一概而论,解决办法也会有不同.在vue中使用echarts的时候,会想要实现window.resize窗体变化大小的时候让图形大小跟着变化.实现的过程中各种bug,也真的让人有种想要发狂的感觉.但是还好,最后在不断的查资料和尝试当中.实现了想要的效果,仅供参考: 首先我这里实现的效果是切换echart图形,然后在window.resize过程中想要实现自适应窗口大小的变化. 这里的两个button分别是控制两个路由切换,也就是两个echart图形(柱状图和饼图)

在vue中使用axios实现跨域请求并且设置返回的数据的格式是json格式,不是jsonp格式

在vue中使用axios实现跨域请求 需求分析:在项目中需要抓取qq音乐的歌曲列表的数据,由于要请求数据的地址url=https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg.从qq音乐的官网上可以看到该请求的请求头中的referer中的域名是y.qq.com(发送请求页面的域名),而host的域名是c.y.qq.com(被请求页面的域名),由于两者不一样,所以不能通过前端直接发送请求给qq服务器去拿数据.这时候需要服务器做一个代理

vue中的slot理解和使用

最近被vue 搞得一塌糊涂,理解的比较慢,工作进度进度要求太快,需求理解不明,造成了很大的压力. 在理解Vue中的Slot的时候看了网上的相关内容,看了半天没看到明白说的是什么,然后自己就安装了vue的相关环境,创建了一个项目,实际动手看看是什么东西, 现理解为: 用父组件的内容去替换掉子组件的内容: 根据父组件中的 <div slot="slot1">slottest</div> 如果引入的子组件中有 <slot name="slot1&quo

vue中解决时间在ios上显示NAN的问题

最近在用vue,遇到倒计时在ios上显示为NAN的问题. 因为做的是倒计时支付,思路是获取服务器时间和下单时间,再转成秒级时间戳做差值. 在网上找到说是ios 不支持例如2018-09-01 10:00:59这种"-"连接符. 网上的解决是: var data = '2018-09-01 12:00:00' var time= Date.parse(new Date(data )) 然后用正则匹配改一下,将-替换为/ var date = '2018-09-01 12:00:00' v