一、BScroll
BScroll是什么?
better-scroll,受iscroll启发,它支持更多功能并具有更好的滚动性能
BetterScroll 是一款重点解决移动端(已支持 PC)各种滚动场景需求的插件。它的核心是借鉴的 iscroll 的实现,它的 API 设计基本兼容 iscroll,在 iscroll 的基础上又扩展了一些 feature 以及做了一些性能优化。
BetterScroll 是使用纯 JavaScript 实现的,这意味着它是无依赖的。
滚动原理
content 高度 > 父容器高度,即可滚动。
在vue中下载better-scroll
cnpm install better-scroll --save
封装组件
<template>
<div ref="wrapper" class="list-wrapper">
<slot></slot>
</div>
</template>
<script>
// @formatter:off
/**
*
* pc段的滚动组件;目前就是简单的滚动效果实现; 有一个问题就是与 饿了么公用的时候
* 在一些弹窗组件弹出的时候回有冲突,可能是 zindex 的计算问题。会导致蒙版在弹窗上面
<div class="scrollbar"> // 必须要保证你的容器 scrollbar 有一个高度
<base-better-scroll>
<div> // 在 scroll 中的内容必须只能有一个标签,否则滚动无效
内容
</div>
</base-better-scroll>
</div>
*/
// @formatter:on
import BScroll from 'better-scroll'
export default {
props: {
/**
* 1 会截流,只有在滚动结束的时候派发一个 scroll 事件。
* 2 在手指 move 的时候也会实时派发 scroll 事件,不会截流。
* 3 除了手指 move 的时候派发scroll事件,在 swipe(手指迅速滑动一小段距离)的情况下,列表会有一个长距离的滚动动画,这个滚动的动画过程中也会实时派发滚动事件
*/
probeType: {
type: Number,
default: 1,
},
// true 是否派发click事件
click: {
type: Boolean,
default: true,
},
// 是否开启横向滚动
scrollX: {
type: Boolean,
default: false
},
// 数据是动态的,数据变了就要重新刷新bascroll否则不能滚动
// 要重新计算dom的高度
// 这里必须安利下:很多时候scroll包裹的dom元素的高度都是动态数据撑开的
// 所以需要在数据变化后,进行重新刷新scroll,才能实现滚动
data: {
type: Array,
default: null,
},
// 是否派发滚动事件
/** 滚动条是否常显示, false: 一直显示, true: 滚动时才显示 */
scrollbarFade: {
type: Boolean,
default: true,
},
/** * 是否派发滚动到底部的事件,用于上拉加载 */
pullup: {
type: Boolean,
default: false
},
/** * 是否派发顶部下拉的事件,用于下拉刷新 */
pulldown: {
type: Boolean,
default: false
},
/** * 是否派发列表滚动开始的事件 */
beforeScroll: {
type: Boolean,
default: false
},
/** * 当数据更新后,刷新scroll的延时。 */
refreshDelay: {
type: Number,
default: 20
}
},
mounted() {
// 为了能正确渲染
// 浏览器刷新一次是17毫秒,所以设置成20毫秒比较合理
//使用this.$nextTick 是一个异步函数,刷新时间是17毫秒,对用户是无感体验
setTimeout(() => {
this.initScrool()
}, 20)
},
methods: {
initScrool() {
if (!this.$refs.wrapper) {//判断实例存不存在
return
}
// better-scroll 对外暴露了一个 BScroll 的类,我们初始化只需要 new 一个类的实例即可。
// 第一个参数就是我们 wrapper 的 DOM 对象,第二个是一些配置参数,
this.scroll = new BScroll(this.$refs.wrapper, {
probeType: this.probeType,
click: this.click,
scrollY: true, // 显示y轴
preventDefault: false, // 在pc端 为 true 的话,可以点选复制文字
scrollbar: {
fade: this.scrollbarFade, // 为 false: 当有滚动条的一直显示,true :只有滚动的时候才显示
interactive: true, // 1.8.0 新增
},
mouseWheel: true, // 开启鼠标滚轮
})
},
// 下面代理几个比较常用的方法
enable() { // 代理better-scroll的enable方法
this.scroll && this.scroll.enable()
},
disable() { // 代理better-scroll的disable方法
this.scroll && this.scroll.disable()
},
refresh() { // 代理better-scroll的refresh方法
this.scroll && this.scroll.refresh()
},
},
data() {
return {}
},
watch: {
// 监听数据的变化,延时refreshDelay时间后调用refresh方法重新计算,保证滚动效果正常
data() {
setTimeout(() => {
this.refresh()
}, 20)
},
},
}
</script>
<style lang="scss">
.list-wrapper {
position: relative;
// height: 100%;
overflow: hidden;
}
</style>
页面使用
//引用组件,内部包裹一个盒子
<base-better-scroll>
<div>
<el-menu
:default-active="$route.path"
unique-opened
:collapse="isCollapse"
:class="{ iconstyle: isCollapse }"
@select="handleSelect"
>
<sidebar-item v-for="(route, index) in menuTree" :key="index" :item="route" />
</el-menu>
</div>
</base-better-scroll>