首先,底部菜单栏最外层是一个div,在div中整体上存在四个或五个小div,每个div中包含icon和text,如下图
对于每一个icon对象,它包含图标以及文字,但十实际中我们肯定不会将img和text写死,以及处于active状态时text的颜色也不会写死,以方便调用者传入想要的参数,这样才算一个彻底的封装。代码如下:
<template>
<div class="tab-bar-item" @click="itemClick">
<div v-if="!isActive">
<slot name="item-icon"></slot>
</div>
<div v-else>
<slot name="item-icon-active"></slot>
</div>
<div :style="activeStyle">
<slot name="item-text"></slot>
</div>
</div>
</template>
<!--
上方代码设置三个插槽,为什么不是两个呢,因为还要包含当item处于活跃状态时要显示的image,所以是三个,使用v-if控制当非活跃时显示默认icon插槽,活跃时显示亮色icon插槽。因为插槽是要被传入其中的内容覆盖的,所以传入的内容可能会将我们slot中的一些属性覆盖掉,所以常常我们需要将slot包裹在div中,这样就可以避免这个问题。
icon下方文同理也放在div中,style绑定一个计算属性,看下方代码可以这个计算属性当item处于活跃时会返回颜色属性,当然这个属性也是可以在调用tab-bar时传入的,默认为红色。
-->
<script>
export default {
name:'TabBarItem',
props:{
path: String, // 当前item对应的路由,由调用者指定
activeColor:{ // 当前item的文字在活跃时的颜色,默认红色,可由使用者指定
type:String,
default:"red"
}
},
data() {
return {
// isActive:false,
}
},
computed:{
// 判断当前item是否处于活跃状态
isActive(){
return this.$route.path.indexOf(this.path)!==-1;
},
// 计算属性,如果处于活跃状态则设置style,否则去除style
activeStyle(){
return this.isActive? {color:this.activeColor}:{};
}
},
methods:{
itemClick(){
if(this.$route.path!==this.path){
this.$router.push(this.path);
// this.isActive = true;
}
}
}
}
</script>
<style scoped>
<!--一些默认样式-->
.tab-bar-item {
flex: 1;
text-align: center;
height: 49px;
font-size: 10px;
}
.tab-bar-item img {
margin-top: 4px;
width: 22px;
height: 22px;
vertical-align: middle;
margin-bottom: 2px;
}
</style>
封装完每一个tabbaritem后,接下来是整体的tabbar,试想,我们肯定还是放入一个插槽代码如下:
<template>
<div id="tab-bar">
<slot></slot>
</div>
</template>
<script>
export default {
name: "TabBar"
};
</script>
<style scoped>
#tab-bar {
display: flex;
background-color: #f6f6f6;
position: fixed;
left: 0;
right: 0;
bottom: 0;
box-shadow: 0px -2px 1px rgba(100, 100, 100, 0.1);
}
</style>
tabbar预留的插槽则用于放入每一个item,我们在这里也是不能写死的,因为控件开发者并不知需要放入多少个item。
使用者在使用我们封装的控件时,则可以如下代码,放入内容:
<template>
<tab-bar>
<tab-bar-item path="/home" activeColor="deepPink">
<img slot="item-icon" src="~assets/img/tabbar/home.svg" alt="">
<img slot="item-icon-active" src="~assets/img/tabbar/home_active.svg" alt="">
<div slot="item-text">首页</div>
</tab-bar-item>
<tab-bar-item path="/category" activeColor="deepPink">
<img slot="item-icon" src="~assets/img/tabbar/category.svg" alt="">
<img slot="item-icon-active" src="~assets/img/tabbar/category_active.svg" alt="">
<div slot="item-text">分类</div>
</tab-bar-item>
<tab-bar-item path="/cart" activeColor="deepPink">
<img slot="item-icon" src="~assets/img/tabbar/cart.svg" alt="">
<img slot="item-icon-active" src="~assets/img/tabbar/cart_active.svg" alt="">
<div slot="item-text">购物车</div>
</tab-bar-item>
<tab-bar-item path="/profile" activeColor="deepPink">
<img slot="item-icon" src="~assets/img/tabbar/profile.svg" alt="">
<img slot="item-icon-active" src="~assets/img/tabbar/profile_active.svg" alt="">
<div slot="item-text">我的</div>
</tab-bar-item>
</tab-bar>
</template>
<script>
import TabBar from "components/tabbar/TabBar";
import TabBarItem from "components/tabbar/TabBarItem";
export default {
name:'MainTabBar',
components:{
TabBar,
TabBarItem
}
}
</script>
<style scoped>
</style>
到此结束。