【Uni】自定义下方导航

自定义导航栏后,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)
},
发布了47 篇原创文章 · 获赞 4 · 访问量 7469

猜你喜欢

转载自blog.csdn.net/weixin_39370093/article/details/100169846
今日推荐