效果图:
组件代码:
<template>
<!-- 自定义底部菜单栏===》模拟小程序菜单栏效果 -->
<div class="tabbar">
<!-- 占位容器===》页面设置占位容器是为了抵消底部导航栏固定定位的高度。 -->
<div class="placegolder-container"></div>
<!-- 底部导航栏 -->
<div class="bottom-tabs">
<!-- tabsList ==》 菜单栏目源数据 -->
<!-- tabsChange(index)==》底部导航栏路由切换点击事件==》传入当前点击的index -->
<div
class="tabs-item"
v-for="(item, index) in tabsList"
:key="index"
@click="tabsChange(index)"
>
<!-- tabIndex 标记当前选中的路由,用于切换菜单栏目 -->
<!-- 不可使用 === 否则会无法匹配成功,可能是因为index值的类型不一样所有无法完全相等 -->
<img
class="tab-tabBarIcon"
:src="tabIndex == index ? item.SelectedSrc : item.notSelectedSrc"
/>
<p class="tab-text" :class="tabIndex == index ? 'active' : ''">
{{ item.text }}
</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Tabbar',
components: {},
data () {
return {
tabIndex: 0,
tabsList: [
{
//! html中使用 :src 动态设置img的路径,需要使用require来设置静态路径,否则会被当作字符串,无法解析图片地址
notSelectedSrc: require('@/assets/tabBarIcon/workSpace.png'),
SelectedSrc: require('@/assets/tabBarIcon/workSpace-action.png'),
text: '我的工作台',
path: '/workingSpace'
},
{
notSelectedSrc: require('@/assets/tabBarIcon/fsl.png'),
SelectedSrc: require('@/assets/tabBarIcon/fsl-action.png'),
text: '防渗漏报验',
path: '/fslHome'
}
]
}
},
created () {
// 一打开页面,就去获取存储在sessionStorage中的 【菜单选中值】
// !==》使用sessionStorage来存储,在刷新页面的时候,依然可以保持(选中/激活)状态
if (sessionStorage.getItem('tabIndex')) {
this.tabIndex = sessionStorage.getItem('tabIndex')
// console.log('之前选中的底部菜单栏是:====>', this.tabIndex)
}
},
methods: {
// 点击tabbar触发事件
tabsChange (index) {
// console.log('点击tabbar==》', index)
// 赋值给data中选中的元素的index,用于切换效果
this.tabIndex = index
// 根据选中的元素的路由,来跳转页面
this.$router.push({
path: this.tabsList[index].path
})
// 设置当前选择的菜单栏元素的index到sessionStorage中去
sessionStorage.setItem('tabIndex', this.tabIndex)
}
},
/**
* 关于 router中配置路由的meta
import Login from '../views/Login.vue'
import CheckList from '../views/CheckListOfList/CheckList.vue'
...
{
path: '/xxx',
component: Xxx,
name: 'xx',
meta: {
//*?自己设置的这个路由对应的index,当网页直接访问到这个路由时,也能在页面里通过监听router的meta来获取到这个index
index: 0,
//*表示这个路由不需要登录,具体要怎么判断,要自己在页面监听或者在【路由守卫】里取到meta里的这个自己设置的字段,来判断
needLogin: false,
title: 'xxx'
}
}
*/
// ! watch 监听的目的是为了在使用【浏览器前进后退】的时候,去监听获取router路由中的meta中设置的index来判断要激活、存储哪个菜单的index
watch: {
/**
* watch 监听 $route,如果直接用,只能监听有children的路由,如果要监听没有子节点的路由,需要
// 深度观察监听
deep: true,
//? 直接触发一次 ,否则监听不到
immediate: true
*/
$route: {
handler: function (newval, oldVal) {
// console.log('监听到路由的新值:')
// console.log(newval.meta.index)
// !监听到当前页面的router中含有index,就赋值给data,设置tabbar的激活样式
// @注意,此处需要加上 ||(或者) 这个判断 因为0本身就相当于false,所以当router的index是0,就无法触发这个if了,所以要加上这个或者的判断
if (newval.meta.index || newval.meta.index === 0) {
this.tabIndex = newval.meta.index
// console.log('当前tabbar的新值:')
// console.log(this.tabIndex)
sessionStorage.setItem('tabIndex', this.tabIndex)
}
},
// 深度观察监听
deep: true,
// 直接触发一次
immediate: true
}
}
}
</script>
<style scoped lang="less">
.tabbar {
position: fixed;
bottom: 0;
left: 0;
}
.placegolder-container {
height: 60px;
}
.bottom-tabs {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 5;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
box-shadow: 0px -1px 1px #e6e6e6;
background-color: #fff;
.tabs-item {
flex: 1;
height: 60px;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
.tab-tabBarIcon {
width: 30px;
height: 30px;
border-radius: 4px;
}
.tab-text {
font-size: 14px;
margin: 0;
&.active {
color: #007aff;
}
}
}
}
</style>
注意:菜单的图标图片需要自己提前准备好
注意:监听路由中的index时,要注意index=0的情况,需要单独判断为0的情况
使用组件:
import Tabbar from '@/components/TabBarComponent.vue'
。。。。
<!-- 底部导航tabbar栏 -->
<Tabbar></Tabbar>
tabBar的图标,要先自己放好,不然是没有图片的,当然,你也可以改成icon,去阿里图标库下载,如何通过阿里图标库下载彩色图标,可以看这两篇博客:
vue引用阿里彩色图标(symbol引用)_五速无头怪的博客-CSDN博客引用阿里图标库的方式有三种,前两种都只能引入单色的图标,对于强迫症简直了,所以俺参考其他大佬的博客,学习了如何通过symbol引用彩色的图标第一步:在阿里图标库选择好自己要的图标,加入购物车,添加至项目,下载到本地这样就把样式文件下载到本地了第二步:在vue项目里面创建对应的inconfont文件夹将这些下载的样式文件放到新建的文件里,方便项目中引用第三步:在main.js中,引入这几个文件(前两个是阿里图标文件,最后一个可以不要,只是自己设置的基础图标宽高等),目的是为了让全...https://blog.csdn.net/black_cat7/article/details/120322471vue引用阿里彩色图标(symbol引用)-封装自己的icon组件_五速无头怪的博客-CSDN博客关于如何引入彩色的阿里图标,请参考另一篇博客:vue引用阿里彩色图标(symbol引用)_五速无头怪的博客-CSDN博客https://blog.csdn.net/black_cat7/article/details/120322471接下来要封装出自己的icon组件,方便使用。第一步:在components文件中新建一个组件(我的叫cjIcon.vue)<template> <!-- symbol方式引用彩色图标,就得这么写 --> <!-- :clashttps://blog.csdn.net/black_cat7/article/details/120324789
代码中我都写了注释,基本都做了说明,可以看懂的~
有几个地方需要注意:
1. router路由的监听与设置
这个组件有watch监听页面的router路由,因为网页是可以通过路由来跳转页面的,如果用户直接通过router路由跳转到tabBar菜单页面,那么就相当于没有点击过菜单,没法触发选中效果,所以通过监听路由,并且在touter.js文件中,给对应的路由设置index键值对,用来判断
router中设置的index,要跟组件中设置的菜单数据顺序一致,因为是通过这个顺序来比对后判断要选中哪个菜单的