better-scroll的封装实现回到顶部按钮
话不多说先上效果:
实现better-scroll封装之前,先了解better-scroll的使用初始化等操作【better-scroll初始化】
better-scroll封装使用说明
scroll组件,将所需要滑动的部分通过插槽的方式传入better-scroll解构。 传入方式:
better-scroll封装后的代码
注意:其中父组件传入的值是用来优化probeType的,因为有的不需要实时监听滚动,根据父组建的需要传入。
<template>
<div class="wrapper" ref="wrapper">
<div class="content">
<slot></slot>
</div>
</div>
</template>
<script>
import BScroll from '@better-scroll/core'
export default {
props:{
ProbeType:{
type:Number,
default:0
}
},
data(){
return{
scroll:null
}
},
mounted(){
//创建BScroll对象
this.scroll = new BScroll(this.$refs.wrapper,{
probeType:this.probeType,//实时监听
pullUpLoad: true,
click:true,//点击有效
observeDOM: true,
mouseWheel:true
})
//2.监听滚动的位置
this.scroll.on("scroll",(position)=>{
//将position传出去
this.$emit("scroll",position);
})
},
methods:{
scrollTo(x,y,time=300){
this.scroll.scrollTo(x,y,time)
}
}
}
</script>
<style scoped>
</style>
父组件使用代码:
<scroll class="content" ref="scroll" :probe-type="3" @scroll="contentScroll">
<swiper :imglink="banners"></swiper>
<recommemd-view :recommends="recommends"></recommemd-view>
<feature-view></feature-view>
<tab-con-trol
class="tabcontrol"
:title="['流行','新款','精选']"
@tabClick="tabClick">
</tab-con-trol>
<goods-list :goods="showGoods"></goods-list>
</scroll>
上面的父子组件调用的代码包含一些父子组件的通信知识 通过 this.$emit("scroll",position); 将实时的滚动信息传给父组件,父组件通过ref="scroll" 来接受子组件传递的scroll的position的信息,进行处理。
vue实现BackTop返回顶部按钮
实现思路 先将top按钮定义点击事件,位置通过flex定位定位到右下角,再使用v-show先进行隐藏TOP按钮默认v-show:"true" ,然后通过封装的scroll组件返回给父组件的position值,position的值是从scroll中获取到的当前滚动条距离顶部的距离,当滚动条达到一定条件的时候进行v-show:"true" ,将TOP按钮放到scroll组件局域的外部,思路可行,代码实现: 代码实现: data中的数据 通过子组件将scroll的实时位置传递给父组件通过this.$emit("scroll",position);//自定义事件,加上值 传递,父组件通过ref="scroll" 接受并通过"@"使用自定义事件@scroll="contentScroll" 将滚动内容放到scroll标签内
<scroll class="content" ref="scroll" :probe-type="3" @scroll="contentScroll">
...滚动内容...
</scroll>
引入知识点,ref是什么东西:
- ref如果在普通的DOM元素上使用,引用指向的就是DOM元素;如果用在子组件上,引用就指向组件中的实例
- 可以通过实例直接调用组件的方法或访问数据,也算是子组件向父组件传值的一种。
$emit(event, args )
参数:
event:事件名、args:事件相关参数
用法:
触发当前实例上的事件。附加参数都会传给监听器回调。
注意:
在组件模板中:
不能直接通过 v-on 绑定触发 vue 实例中的方法,而需要先使用$emit( ) 绑定自定义事件,把自定义事件发射出去(发射到html 层面);
然后在html 层面:
组件自定义元素上,绑定自定义事件和vue 实例中的方法,以此实现组件和vue 实例方法的绑定。
@scroll="contentScroll"自定义事件,传过来的值position,根据position来来判断是否显示TOP按钮
contentScroll(position){
console.log(position.y);
this.tabcontrol_xiding_logic = -position.y>533
this.backtoplogic = -position.y>800
},
实现效果: 存留问题,回到顶部的按钮点击后回到顶部的速度太快,使用better-scroll自带的方法可进行返回顶部的时间设置
methods:{
scrollTo(x,y,time=300){
this.scroll.scrollTo(x,y,time)
}
}
父组件调用该代码使用了$refs进行直接调用子组件的方法:
backtopclick(){
this.$refs.scroll.scrollTo(0,0,500)
},
当然,better-scroll使用后,吸顶效果也会失效,创建另一个吸顶效果的HTML代码放到scroll局域的外面,通过data定义的变量进行判断是否显示,实现方法也是如此。
上面总结的如果比较乱,那么完全代码如下: Home.vue【父组件】代码
<template>
<div id="home">
<nav-bar class="home-nav"><div slot="center">购物街</div></nav-bar>
<!-- <div class="wrapper">
<div class="content">
<swiper :imglink="banners"></swiper>
<recommemd-view :recommends="recommends"></recommemd-view>
<feature-view></feature-view>
<tab-con-trol
class="tabcontrol"
:title="['流行','新款','精选']"
@tabClick="tabClick">
</tab-con-trol>
<goods-list :goods="showGoods"></goods-list>
</div>
</div> -->
<scroll class="content" ref="scroll" :probe-type="3" @scroll="contentScroll">
<swiper :imglink="banners"></swiper>
<recommemd-view :recommends="recommends"></recommemd-view>
<feature-view></feature-view>
<tab-con-trol
class="tabcontrol"
:title="['流行','新款','精选']"
@tabClick="tabClick">
</tab-con-trol>
<goods-list :goods="showGoods"></goods-list>
</scroll>
<tab-con-trol
class="tabcontrol_xiding"
:title="['流行','新款','精选']"
@tabClick="tabClick" v-show="tabcontrol_xiding_logic">
</tab-con-trol>
<back-top class="backtop" @click.native="backtopclick" v-show="backtoplogic"></back-top>
<ul>
li{第$个li}*1000
</ul>
</div>
</template>
<script>
import NavBar from "components/common/Homenavbar/NavBar.vue";
import Swiper from 'components/common/swiper/swiper'
import RecommemdView from 'components/common/HomerecommendView/recommendview.vue'
import FeatureView from "components/common/HomefeatureView/feature.vue"
import Scroll from 'components/common/scroll/scroll.vue'
import TabConTrol from "components/content/TabControl/tabcontrol.vue"
import GoodsList from "components/content/goods/GoodsList.vue"
import BackTop from "components/content/BackTop/BackTop.vue"
import {getHomeMultidata,getHomeGoods} from "network/home";
export default {
name:"Home",
data(){
return {
banners:[],
recommends:[],
goods:{
"pop":{page:0,list:[]},
"new":{page:0,list:[]},
"sell":{page:0,list:[]},
},
currentType:"pop",
tabcontrol_xiding_logic:false,
backtoplogic:false,
}
},
computed:{
showGoods(){
return this.goods[this.currentType].list
}
},
components:{
NavBar,
Swiper,
RecommemdView,
FeatureView,
TabConTrol,
GoodsList,
Scroll,
BackTop,
},
created(){
//1.请求多个数据
this.getHomeMultidata();
//请求“新款”,“流行”,“精选”的商品数据
this.getHomeGoods('pop');
this.getHomeGoods('new');
this.getHomeGoods('sell');
},
methods:{
/**
* 事件监听相关的方法
*/
tabClick(index){
switch(index){
case 0:
this.currentType = "pop";
break;
case 1:
this.currentType = "new";
break;
case 2:
this.currentType = "sell";
break;
}
console.log(index);
},
backtopclick(){
this.$refs.scroll.scrollTo(0,0,500)
},
contentScroll(position){
console.log(position.y);
this.tabcontrol_xiding_logic = -position.y>533
this.backtoplogic = -position.y>800
},
/**
* 网络请求相关方法
*/
getHomeMultidata(){
getHomeMultidata().then(res=>{
this.banners = res.data.data.banner.list;
this.recommends = res.data.data.recommend.list;
})
},
getHomeGoods(type){
const page = this.goods[type].page + 1;
getHomeGoods(type,page).then(res=>{
this.goods[type].list.push(...(res.data.data.list));
this.goods[type].page += 1
})
},
}
}
</script>
<style scoped>
padding-top:44px;
height: 100vh;
position: relative;
}
.home-nav{
background-color: var(--color-tint);
color: white;
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 9;
}
.tabcontrol{
background-color: white;
/* position: sticky;
top: 44px; */
z-index: 999;
}
.tabcontrol_xiding{
background-color: white;
position: absolute;
top: 44px;
width: 100%;
}
.content{
height:calc(100vh - 93px);
overflow: hidden;
padding-bottom: 10px;
}
.backtop{
z-index: 100000;
}
</style>
scroll.vue【子组件】代码:封装代码
<template>
<div class="wrapper" ref="wrapper">
<div class="content">
<slot></slot>
</div>
</div>
</template>
<script>
import BScroll from '@better-scroll/core'
export default {
props:{
ProbeType:{
type:Number,
default:0
}
},
data(){
return{
scroll:null
}
},
mounted(){
//创建BScroll对象
this.scroll = new BScroll(this.$refs.wrapper,{
probeType:this.probeType,//实时监听
pullUpLoad: true,
click:true,//点击有效
observeDOM: true,
mouseWheel:true
})
//2.监听滚动的位置
this.scroll.on("scroll",(position)=>{
//将position传出去
this.$emit("scroll",position);
})
},
methods:{
scrollTo(x,y,time=300){
this.scroll.scrollTo(x,y,time)
}
}
}
</script>
<style scoped>
</style>
最终效果:
|