自定义导航栏后,Uni原生的tabbar切换时会出现闪屏的问题,使用跳转( uni.navigateTo )也有这个问题,使用重定向(uni.redirectTo)又不符合我们的初衷,于是再用Vue组件切换的形势来实现,点击下方tab时切换页面的操作。
效果
转换格式的时候颜色就变了下面是原来的颜色
其实原理很简单就是使用组件,之后v-if、v-else-if、v-else来控制控件的出现(使用:is被提示说暂不支持动态组件)
上代码
文档目录
index.vue:
<template>
<view class="content" @click="isShowPop=false">
<!-- 上方显示时间 显示wifi的通栏 -->
<view class="status_bar">
<view class="top_view"></view>
</view>
<view class="nav">
<view class="nav-title">{{title}}</view>
<view class="nav-contorls" v-if="title=='Gecer'">
<view class="iconfont icon-sousuo"></view>
<view class="iconfont icon-tianjia" @click.stop="isShowPop=!isShowPop"></view>
</view>
<view class="mune-pop" v-if="isShowPop">
<view class="iconfont icon-tianjiahaoyou">
添加好友
</view>
<view class="iconfont icon-daifukuan">
收付款
</view>
<view class="iconfont icon-youjian">
帮助与反馈
</view>
</view>
</view>
<view class="main" :style="{'height':'calc(100% - '+(statusBarHeight+50+70)+'px)'}">
<mainPage v-if="page=='main'"></mainPage>
<mailPage v-else-if="page=='mail'"></mailPage>
<findPage v-else-if="page=='find'"></findPage>
<mePage v-else></mePage>
</view>
<view class="footer">
<view v-for="(item,index) in meuns" :key='index' :class="{'isClick':item.isClick}" @click="changeMune(item)">
<view :class="['iconfont',item.icon]">
</view>
<view class="footer-desc">{{item.desc}}</view>
</view>
</view>
</view>
</template>
<script>
import mainPage from '../../conponents/mainPage.vue'
import mailPage from '../../conponents/mailPage.vue'
import findPage from '../../conponents/findPage.vue'
import mePage from '../../conponents/mePage.vue'
export default {
components:{
mainPage,
mailPage,
findPage,
mePage
},
data() {
return {
page:'main',
title: 'Gecer',
isShowPop: false,
statusBarHeight: 0,
meuns:[
{
icon:'icon-liaotian',
path:'main',
desc:'Gecer',
isClick:true
},
{
icon:'icon-tongxunlu',
path:'mail',
desc:'通讯录',
isClick:false
},
{
icon:'icon-faxian',
path:'find',
desc:'发现',
isClick:false
},
{
icon:'icon-buoumaotubiao03',
path:'me',
desc:'我',
isClick:false
}
]
}
},
onLoad() {
console.log('onLoad')
},
created() {
let $this = this;
setTimeout(() => {
uni.getSystemInfo({
success(res) {
console.log(res.statusBarHeight)
$this.statusBarHeight = res.statusBarHeight;
}
})
}, 1)
},
methods: {
changeMune(item){
this.meuns.forEach(x=>{
x.isClick=false;
})
item.isClick=true;
if(item.path){
this.page=item.path;
this.title=item.desc;
}
}
}
}
</script>
<style scoped>
.content {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
}
//上方手机状态栏 通栏
.status_bar {
height: var(--status-bar-height);
width: 100%;
background-color: #545454;
}
.top_view {
height: var(--status-bar-height);
width: 100%;
position: fixed;
background-color: #545454;
top: 0;
z-index: 999;
}
//导航
.nav {
position: relative;
display: flex;
width: 100%;
height: 50px;
justify-content: space-between;
align-items: center;
background: #EFEFEF;
}
.nav-title {
margin-left: 10px;
font-size: 20px;
font-weight: bold;
}
//导航按钮
.nav-contorls {
display: flex;
}
.nav-contorls view:nth-child(1) {
margin-right: 8px;
}
.nav-contorls view {
padding: 10px;
border-radius: 8px;
}
.nav-contorls view:active {
background: #C0C0C0;
}
.nav-contorls {
margin-right: 10px;
}
.nav-contorls .iconfont {
font-size: 25px;
}
.mune-pop {
position: absolute;
top: 50px;
right: 10px;
width: 180px;
background: #545454;
margin-top: 5px;
border-radius: 8px;
}
.mune-pop:after {
position: absolute;
top: -5px;
right: 15px;
content: '';
height: 0;
width: 0;
border-bottom: 8px solid #545454;
border-right: 9px solid transparent;
border-left: 9px solid transparent;
}
.mune-pop>view {
color: white;
font-size: 20px;
margin: 10px 0 10px 20px;
height: 40px;
line-height: 40px;
border-bottom: 1px solid #808080;
}
.mune-pop .iconfont:before {
margin-right: 10px;
}
//主体内容
.main {
width: 100%;
background: white;
}
//下方导航
.footer {
width: 100%;
height: 70px;
background: #F8F8F8;
display: flex;
justify-content: space-between;
align-items: center;
}
.footer>view {
padding: 5px 0;
text-align: center;
margin: 0 10px 0 10px;
width: 70px;
height: 50px;
border-radius: 8px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.footer>view:nth-child(1) {
margin: 0 10px 0 20px;
}
.footer>view:nth-child(4) {
margin: 0 20px 0 10px;
}
.footer .iconfont {
font-size: 26px;
height: 24px;
}
.footer-desc {
font-size: 16px;
}
.isClick {
background: #7ED33E;
color: white;
}
</style>
组件里面的代码都差不多就在这写一个mainPage.vue
<template>
<view class="main">main</view>
</template>
<script>
export default{
data(){
return{
}
}
}
</script>
<style scoped>
.main{
height: 100%;
}
</style>
注意要点,就是下方导航定位的问题
看这里
<view class="main" :style="{'height':'calc(100% - '+(statusBarHeight+50+70)+'px)'}">
<mainPage v-if="page=='main'"></mainPage>
<mailPage v-else-if="page=='mail'"></mailPage>
<findPage v-else-if="page=='find'"></findPage>
<mePage v-else></mePage>
</view>
calc 里面 100%- statusBarHeight -上方自定义导航高度-下方导航高度
statusBarHeight 就是状态栏的高度,状态栏的高度uni提供了接口
uni.getSystemInfo({
success(res) {
$this.statusBarHeight = res.statusBarHeight;
}
})
要是直接这么写会报错,为啥会报错我也没整明白,不过倒是查到了解决方案,使用setTimeout使之变成异步的
created() {
let $this = this;
setTimeout(() => {
uni.getSystemInfo({
success(res) {
$this.statusBarHeight = res.statusBarHeight;
}
})
}, 1)
},