需求:移动端h5,页面顶部有nav-bar,下部有tab-bar,缺少中间内容盒子,当tab-bar页面切换时,页面滚动位置丢失,导致交互类似页面重新渲染
根据这种需求,就衍生出了scroll-view组件,下面是我结合vant实现的简易的scroll-view
首先是tab集合页
<template>
<section>
<van-nav-bar :title="title" :left-arrow="false" :fixed="true" />
<transition>
<keep-alive>
<home v-if="active==0"></home>
<classify v-else-if="active==1"></classify>
<shop-car v-else-if="active==2"></shop-car>
<find v-else-if="active==3"></find>
<mine v-else-if="active==4"></mine>
</keep-alive>
</transition>
<van-tabbar v-model="active">
<van-tabbar-item icon="home-o">首页</van-tabbar-item>
<van-tabbar-item icon="apps-o">分类</van-tabbar-item>
<van-tabbar-item icon="shopping-cart-o">购物车</van-tabbar-item>
<van-tabbar-item icon="point-gift-o">发现</van-tabbar-item>
<van-tabbar-item icon="user-o">我的</van-tabbar-item>
</van-tabbar>
</section>
</template>
<script>
import Home from "@/views/Home.vue";
import Classify from "@/views/Classify.vue";
import shopCar from "@/views/shopCar.vue";
import Find from "@/views/Find.vue";
import Mine from "@/views/Mine.vue";
export default {
components: {
home: Home,
classify: Classify,
"shop-car": shopCar,
find: Find,
mine: Mine
},
data() {
return {
active: 0
};
},
computed: {
title: function() {
let title = "首页";
switch (this.active) {
case 0:
title = "首页";
break;
case 1:
title = "分类";
break;
case 2:
title = "购物车";
break;
case 3:
title = "发现";
break;
case 4:
title = "";
break;
}
return title;
}
},
methods: {},
mounted() {}
};
</script>
<style>
.van-nav-bar--fixed {
background: linear-gradient(to right, #ff9700, #ed1c24);
}
.van-nav-bar__title {
color: #fff;
}
.van-tabbar-item--active {
color: #f65a10;
}
</style>
此页面使用keep-alive防止tab切换时导致组件被销毁
就用首页作为示例页
<template>
<div id="scroll_fa">
<scroll-view id="scroll_box" scroll-y="true" @getScrollTop="getScrollTop" @reachBottom="onReachBottom">
<div id="page">
<van-pull-refresh v-model="isLoading" @refresh="onRefresh">
<div v-for="(item,index) in 100" :key="index">this is home</div>
</van-pull-refresh>
</div>
</scroll-view>
</div>
</template>
<script>
export default {
data() {
return {
isLoading: false
};
},
methods: {
onRefresh() {
setTimeout(() => {
this.$toast("刷新成功");
this.isLoading = false;
this.count++;
}, 500);
},
getScrollTop(e){
window.console.log(e)
},
//触底事件
onReachBottom(){
window.console.log('触底');
}
},
mounted() {
this.$toast("重载");
}
};
</script>
<style scoped>
#scroll_fa{
width: 100%;
position: fixed;
z-index:1;
top: 45px;
bottom: 50px;
}
#scroll_box{
width: 100%;
height: 100%;
}
#page {
width: 100%;
min-height: 100%;
}
</style>
scroll-view组件采用全局注册,故未在此页面引入,下面是scroll-view的代码
<template>
<div v-bind:class="{'my_scroll_container':true}" @scroll="getScroll" :style="`${scrollX==='true'||scrollX===true?'overflow-x:scroll;overflow-y:hidden':''};${scrollY==='true'||scrollY===true?'overflow-x:hidden;overflow-y:scroll':''};`">
<slot></slot>
</div>
</template>
<script>
export default {
props: {
scrollX:{
type:[String,Boolean],
value:false
},
scrollY:{
type:[String,Boolean],
value:false
}
},
data() {
return {
scrollTop: 0
};
},
methods: {
//滚动事件
getScroll(e) {
let wScrollY = e.target.scrollTop; // 当前滚动条位置
this.scrollTop = wScrollY;
let wInnerH = e.target.clientHeight; // 设备窗口的高度(不会变)
let bScrollH = e.target.scrollHeight; // 元素总高度
if (wScrollY + wInnerH >= bScrollH) {
this.$emit("reachBottom");
}
}
},
activated() {
this.$el.scrollTop = this.scrollTop;
this.$emit('getScrollTop',{scrollTop:this.scrollTop});
},
updated() {},
mounted() {}
};
</script>
<style scoped>
.my_scroll_container{
width: 100%;
height: 250px;
}
</style>
至此就实现了scroll-view的滚动位置记录,和触底事件