目录
前言
betterScroll的大多数使用在移动端浏览器上面,因为旧版移动端原生滑动过于生硬,而新版没有下拉缓冲,这样对于客户来说并不友好,而betterScroll不仅解决这些问题,还配套了不少插件使用。
工具
"@better-scroll/core": "^2.5.1",
"@better-scroll/mouse-wheel": "^2.5.1",
"@better-scroll/observe-dom": "^2.5.1",
"vue": "^3.2.13",
(个人觉得这个是非常重要的,因为我不知道你是什么时候阅读的这篇文章,技术有没有更新,因为版本不同,用法可能也不同了,我这篇文章也就不能帮助到你)
一、betterScroll是什么?
betterScroll,官网上是叫BetterScroll 2.0,我这里就不水字数了,官网链接呈上......
https://better-scroll.github.io/docs/zh-CN/guide/
(我是非常建议大家通过读官网文档进行学习的,第一次读可能不习惯,但慢慢来就好。当然,你都去读文档了还来我这里干啥?)
二、使用步骤
1.引入库
代码如下:(这个是npm的)
npm install @better-scroll/core --save
代码如下:(yarn下载,因为可能你网速很拉,就建议这个了...)
yarn add @better-scroll/core
2.功能实现
不急于立马封装,先试试能不能实现功能,再进行封装(代码还是得有颜色的才好看...)
这是最基本的用法,效果如下
从这里我们可以看到:
- 我们可以按住绿色部分上下拖动
- 使用betterScroll内的代码中的BScroll构造函数需要传入wrapper元素对象
- 整个结构分为两层,一个是content内容区,该区域是可以上下拖动的,另一个是wrapper,当然,wrapper可以加个overflow:hidden隐藏超出的绿色部分
- 目前只能拖动,不可以滚动(滚动需要下载额外插件,后文会说...)
效果如下:
慢慢接近预期效果了
那么问题来了,如果没有content这个元素,直接在wrapper内塞满多个div是不是也可以拖动呢?
代码如下所示:
<template>
<div class="wrapper">
我是wrapper
<div class="item">
item
</div>
<div class="item">
item
</div>
<div class="item">
item
</div>
<div class="item">
item
</div>
<div class="item">
item
</div>
<div class="item">
item
</div>
<div class="item">
item
</div>
<div class="item">
item
</div>
<!-- <div class="content">
我是content
</div> -->
</div>
</template>
<script setup>
import { onMounted } from "vue";
import BScroll from '@better-scroll/core'
onMounted(() => {
let wrapper = document.querySelector('.wrapper')
let scroll = new BScroll(wrapper)
})
</script>
<style>
.wrapper {
width: 200px;
height: 200px;
background-color: red;
overflow: hidden;
}
.content {
width: 80%;
height: 400px;
background-color: green;
}
.item {
width: 100%;
height: 30px;
background-color: green;
margin-bottom: 3px;
}
</style>
效果如下:
实验可以知道,代码是无法拖动的,丧失了进本的拖动功能,内部元素已经溢出了,为啥不行呢?
这个在betterScroll官网也是有解释的(还是我来解释吧),其实就是说,上面的content是必须的,当实例化BScroll时候传入了wrapper,那么该wrapper元素内部必须要有一个content元素,最好只有一个,当该content元素wrapper元素高度时候,content元素就可以上下拖动了,很多人都是这个地方一上来就放了很多div元素,到最后不能拖动,然后就疯狂csdn开搜(我就在这等着了...)。
工具包有许多亮眼的功能,但是呢,使用者必须遵守开发者的使用规则才行。(就好比自行车,开发出自行车的人可没希望你用它来打架是吧?)
3.添加滚轮功能
滚轮功能需要下载另外的npm包,命令呈上...
npm install @better-scroll/mouse-wheel --save
代码呈上...
<template>
<div class="wrapper">
我是wrapper
<div class="content">
我是content
</div>
</div>
</template>
<script setup>
import { onMounted } from "vue";
import BScroll from '@better-scroll/core'
import MouseWheel from "@better-scroll/mouse-wheel"
BScroll.use(MouseWheel)
onMounted(() => {
let wrapper = document.querySelector('.wrapper')
let scroll = new BScroll(wrapper, {
mouseWheel: {
speed: 20,
invert: false,
easeTime: 300
}
})
})
</script>
<style>
.wrapper {
width: 200px;
height: 200px;
background-color: red;
overflow: hidden;
}
.content {
width: 80%;
height: 400px;
background-color: green;
}
.item {
width: 100%;
height: 30px;
background-color: green;
margin-bottom: 3px;
}
</style>
然后?然后就可以滚动了...
三、回归业务
我们从上面的使用步骤可以知道,betterScroll需要一个wrapper元素在外,内部还得嵌入一个content元素(当然类名可以随便取,我这边方便讲解就用了官方的命名,只需要在new BScroll时候注意传入的参数是外标签元素就行了),但是我们可以解决什么样的业务呢?
我这边就开一个项目中常见的例子,我们在onMounted中请求一个数组数据,然后将这数组数据放入到content元素内,使得content元素高度被内部元素撑开而大于wrapper元素高度,然后就可以通过上下拖动或者滚轮浏览一个数组的数据,这样是不是也做成了一个浏览列表的业务呢?
<template>
<div class="wrapper">
我是wrapper
<div class="content">
<div v-for="item in list" class="item">
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import BScroll from '@better-scroll/core'
import MouseWheel from "@better-scroll/mouse-wheel"
import ObserveDom from "@better-scroll/observe-dom"
BScroll.use(ObserveDom)
BScroll.use(MouseWheel)
const list = ref([])
onMounted(() => {
let wrapper = document.querySelector('.wrapper')
let scroll = new BScroll(wrapper, {
mouseWheel: {
speed: 20,
invert: false,
easeTime: 300
},
observeDOM: true
})
setTimeout(() => {
list.value = [{
name: "周洋",
age: "12"
},
{
name: "宋吉",
age: "16"
},
{
name: "周易",
age: "15"
},
{
name: "门江",
age: "12"
},
{
name: "仓尔西",
age: "23"
},
{
name: "周鑫燚",
age: "11"
},
{
name: "仓吱吱",
age: "5"
}]
}, 3000)
})
</script>
<style>
.wrapper {
width: 200px;
height: 200px;
background-color: red;
overflow: hidden;
}
.content {
width: 80%;
/* height: 400px; */
/* background-color: green; */
}
.item {
border-radius: 6px;
width: 100%;
height: 30px;
background-color: green;
margin-bottom: 3px;
}
</style>
总结:寄,拖动不行,滚动也不行,完结...(开个玩笑)
下面是解决方案:
先下载这个包
npm install @better-scroll/observe-dom --save
代码修改如下:
<template>
<div class="wrapper">
我是wrapper
<div class="content">
<div v-for="item in list" class="item">
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import BScroll from '@better-scroll/core'
import MouseWheel from "@better-scroll/mouse-wheel"
import ObserveDom from "@better-scroll/observe-dom"
BScroll.use(ObserveDom)
BScroll.use(MouseWheel)
const list = ref([])
onMounted(() => {
let wrapper = document.querySelector('.wrapper')
let scroll = new BScroll(wrapper, {
mouseWheel: {
speed: 20,
invert: false,
easeTime: 300
},
observeDOM: true
})
setTimeout(() => {
list.value = [{
name: "周洋",
age: "12"
},
{
name: "宋吉",
age: "16"
},
{
name: "周易",
age: "15"
},
{
name: "门江",
age: "12"
},
{
name: "仓尔西",
age: "23"
},
{
name: "周鑫燚",
age: "11"
},
{
name: "仓吱吱",
age: "5"
}]
}, 3000)
})
</script>
<style>
.wrapper {
width: 200px;
height: 200px;
background-color: red;
overflow: hidden;
}
.content {
width: 80%;
/* height: 400px; */
/* background-color: green; */
}
.item {
border-radius: 6px;
width: 100%;
height: 30px;
background-color: green;
margin-bottom: 3px;
}
</style>
是不是发现又行了 ?为啥之前的正常,这次就需要下载一个包了?之前正常是因为实例化BScroll时候,content已经拥有了高度,当时我们设置的高度是400px,然后BScroll构造函数内可以获得这个400px计算我们可以拖动和滚动的距离,并计算下拉缓冲位置,而这次我们content是3秒后被内部div标签元素撑开的,实例化BScroll时候获取的content高度是0,也就无法计算出滚动和拖动的距离,所以就不行了,而加入了这个@better-scroll/observe-dom,配置好后,就相当于给BScroll一个监视器,当内部content元素高度变化之后,他会重新获取content元素的高度,进而重新计算滚动和拖动的距离,所以我们又行了。
四、封装成组件
能解决业务,嗯,可以封装成组件了...
组件代码如下
<template>
<div class="wrapper">
<div class="content">
<slot></slot>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import BScroll from '@better-scroll/core'
import MouseWheel from "@better-scroll/mouse-wheel"
import ObserveDom from "@better-scroll/observe-dom"
BScroll.use(ObserveDom)
BScroll.use(MouseWheel)
onMounted(() => {
let wrapper = document.querySelector('.wrapper')
let scroll = new BScroll(wrapper, {
mouseWheel: {
speed: 20,
invert: false,
easeTime: 300
},
observeDOM: true
})
})
</script>
<style scoped>
.wrapper {
width: 200px;
height: 400px;
/* background-color: red; */
border: solid 1px #ddd;
overflow: hidden;
}
.content {
width: 100%;
/* height: 400px; */
/* background-color: green; */
}
</style>
这样子使用...
<template>
<Wrapper class="wrapper">
<div v-for="item in list" class="item">
</div>
</Wrapper>
</template>
<script setup>
import Wrapper from "@/components/Wrapper.vue"
import { onMounted, ref } from "vue";
const list = ref([])
onMounted(() => {
setTimeout(() => {
list.value = [{
name: "周洋",
age: "12"
},
{
name: "宋吉",
age: "16"
},
{
name: "周易",
age: "15"
},
{
name: "门江",
age: "12"
},
{
name: "仓尔西",
age: "23"
},
{
name: "周鑫燚",
age: "11"
},
{
name: "仓吱吱",
age: "5"
}]
}, 3000)
})
</script>
<style scoped>
.wrapper {
width: 200px;
height: 200px;
}
.item {
border-radius: 6px;
width: 100%;
height: 30px;
background-color: green;
margin-bottom: 3px;
}
</style>
这里使用了vue3的插槽,将组件标签内的所有元素放入到content中。我看我身边同学很多都喜欢写内联样式,其实挺不建议的,就通过上例来说,我们在组件中使用样式表给wrapper写了宽高样式,这样当作默认的宽高,如果我们想使用时候修改,我们可以给组件标签添加样式表(组件内最好只有一个标签保住所有标签,这样,外部的样式表在构建时候就会添加到组件最外部),外部的样式表和组件内部样式表会进行一个整合,当外部样式表和组件内样式表有相同属性时候,他会优先使用外部的,但如果我们在组件内使用内联样式,外部添加给组件的相同属性样式(比如宽高)就会不生效,当然如果你不设置默认宽高的话...
五、总结
如果我的文章有帮到你的话我是很开心的,当然篇幅有些长...如果有什么更好的建议或者能够为我纠错的话欢迎评论喔.......