在做主页的页面时,想实现鼠标左键,即可上下滑动的过程。因此,通过观看博客与资料,发现better-scroll是一个非常好用的插件。接下来,记录下做此功能的时候,实现到的一些学习。
BetterScroll 是一款重点解决移动端各种滚动场景需求的开源插件(可以在GitHub上找到其资源),适用于滚动列表、选择器、轮播图、索引列表、开屏引导等应用场景。
首先的话,先输入npm install better-scroll --save来进行安装,因为版本需要稳定的原因,我没有选择最新版。而是在下载安装完成之后,手动在package,json中,将版本改为了1.13.2,之后在输入npm install,全局安装下即可。
接下来,我先拿了一个html文件作为实验,在node_modules文件夹中,找到了bscroll.js文件,将它复制到了一个新的文件夹中,在html文件中,通过:<script src="./bscroll.js"></script>,而引入。
接下来,我们来做真正的实现。
其常见的,html结构为:
<div class="wrapper"> <ul class="content"> <li>...</li> <li>...</li> ... </ul> </div>
需要记住,这个类为wrapper的父元素中,智能包含一个元素,而这个元素中允许包含许多个子元素。接下来,是我初次学习这个插件的时候,学习的写的一些代码。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .content{ height: 150px; background-color: #bfbf0d; overflow: hidden; } </style> </head> <body> <div> <div class="content"> <!-- content 里面只能包含一个元素--> <ul> <button class="btn">按钮1</button> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> <li>1</li> </ul> </div> </div> <script src="./bscroll.js"></script> <script> //默认情况下,BScroll是不可以实时监听滚动位置,probe侦测,0、1都不侦测 //2的话,手指滚动的过程中是侦测的,但是手指离开后惯性滚动的内容是不侦测的。 //3的话,是指只要滚动过程当中,那么都会侦测。 const bscroll = new BScroll(document.querySelector(".content"),{ probeType: 3, click:true, pullUpLoad:true }) bscroll.on("scroll",(position) =>{ // console.log(position); }) bscroll.on("pullingUp",()=>{ console.log("上拉加载更多") //发送网络请求,请求更多页的数据 //等待数据请求完成,并且将新的数据显示出来后 setTimeout(()=>{ bscroll.finishPullUp() },2000) }) document.querySelector(".btn").addEventListener("click",function (){ console.log("------") }) </script> </body> </html>
我们来归纳比较重要的几个重要的points。
索引列表,首先需要在滚动过程中实时监听滚动到哪个索引的区域了,来更新当前索引。在这种场景下,我们可以使用probeType
选项。当probeType设置为0、1时,那么都不会侦测。当probeType设置为2时,手指滚动的时候,都是侦测的。但是,手指离开后,即使是通过惯性所滚动的数据,都不会被侦听。当此选项设置为 3 时,会在整个滚动过程中实时派发 scroll 事件。从而获取滚动过程中的位置。pullUpLoad
选项,用来配置上拉加载功能。当设置为 true 或者是一个 Object 的时候,可以开启上拉加载,可以配置离底部距离阈值(threshold)来决定开始加载的时机。注意,如上述代码所显示,若仅仅是在bscroll中使用pullIUpLoad选项,且使用bscroll.on(“pullingUp”,()=>{console.log(“上拉加载更多”}),无论拉多少次,但只能显示一次。因此,为了可以显示多次,且延期段时间,我在后面设置了setTimeout函数,这样即可实现显示多次了。click设置为true,也是十分重要的,后期做项目的时候即有显示。
setTimeout(()=>{
bscroll.finishPullUp()
},2000)
})
接下来,我们来看下项目当中的实际应用。最初我知道的实现滚动,只有在css中直接设置,overflow:scroll。在移动端,如果仅使用,overflow:scroll生成一个滚动容器,会发现它的滚动是比较卡顿,呆滞的。因为,我们早就习惯了目前主流操作系统与浏览器视窗的滚动体验,比如滚动到边缘即会有回弹,手指停止滑动,还会按惯性继续滚动一会,手指快速滑动时页面会快速滚动。而原生的却没有,会有一定的卡顿感。我的应用,主要是在首页中,实现鼠标左键直接可拖动滑滚。为了之后,这个功能可以实现在不同的页面,因此我在component文件见中的common文件夹中,添加了一个scroll文件。且在其中创建了一个scroll.vue,代码如下:
<template> <div class="wrapper" ref="wrapper"> <div class="content"> <slot></slot> </div> </div> </template> <!--//ref如果是绑定在组件中的,那么通过this.$refs.refname获取到的是一个组件对象--> <!--//ref如果绑定在普通元素中,那么会通过this.$refs.refname获取的一个元素对象--> <script> import BScroll from "better-scroll" export default { name: "scroll", data(){ return{ scroll:null } }, mounted(){ this.scroll = new BScroll(this.$refs.wrapper,{ click:true }) } } </script> <style scoped> </style>
接下来做两点解释:
1.<template>模块,中为什么要使用,两层<div>来包裹住插槽。文中上述部分也看到了,better-scroll中的基本格式,就是wrapper类的父元素只包裹一个元素,而此元素里面则可以包含许多元素。(这里留下的<slot>,以home这页面而言的话,是为了能够灵活滚动几个组件的)。
2.之后在mounted中的时候,尽量不要使用document.querySelector('wrapper'),因为无法确定项目中,是否其他部分也有类名为wrapper的。因此,使用ref来针对性指定。ref被用来给DOM元素或子组件注册引用信息。引用信息会根据父组件的$refs对象进行注册。如果在普通的DOM元素上使用,引用信息就是元素。如果用在子组件上,引用信息就是组件实例。
接下来,来看下home.vue中的实现,这里只贴与此相关的代码。
<template> <div class="homie"> <navbar class="home-nav"><div slot="center">购物街</div> </navbar> <scroll class="content"> <homeswiper :banners="banners"></homeswiper> <reco :recommends="recommends"></reco> <featureview></featureview> <tabcontrol :titles="['流行','新款','精选']" class="tab-control" @tabclick="tabclick"> </tabcontrol> <goodslist :goods="showgoods"></goodslist> </scroll> </div> </template> <script> import scroll from "../../src/components/common/scroll/scroll"; export default { name: "home", components:{ navbar, homeswiper, reco, featureview, tabcontrol, goodslist, scroll } </script> <style scoped> .homie{ color: black; padding-top: 44px; padding-bottom: 49px; position: relative; height: 100vh; } .content{ height: calc(100vh - 89px); overflow-y: hidden; } </style>
首先,就是在home中注册这个组件,并使用。先是import了scroll,之后的话在<template>中使用了<scroll>,且其中包裹了需要滑动的组件们。
后面的content中不需要再使用ref的原因是因为,<style scoped>在vue文件中的style标签上。当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,也就是说,该样式只能适用于当前组件元素。通过该属性,可以使得组件之间的样式不互相污染。如果一个项目中的所有style标签全部加上了scoped,相当于实现了样式的模块化。height使用了calc函数,因为我的tabbar与navbar的高度加在一起为89px。使用calc函数的时候,记住需要在符号左右有所空格。由于1vh就等于视口高度的百分之一,则我直接设置整体为100vh即可。我在做完上述步骤后,实现了可以灵活滚动,但是点击被<scroll>包裹的那些组件中的商品详情,图片,轮播图等等都无法跳转了,然而在我做小demo的时候,发现使用<button>的时候,无论设置click为true或者false,都可以使用。然而要是对<div>或者组件元素的话,要设置为可点击的话,必须设置在scroll中设置click为true。