uni-app 实现自定义底部导航

原博:https://juejin.cn/post/7365533404790341651

在开发微信小程序,通常会使用uniapp自带的tabBar实现底部图标和导航,但现实有少量应用使用uniapp自带的tabBar无法满足需求,这时需要自定义底部tabBar功能。 例如下图的需求,在中间添加一个加号,例如根据不同登录的角色显示不同的tabBar按钮等,这些功能在无法通过 uniapp自带的tabBar实现所以需要写相关组件逻辑。

常规tabBar

常规实现底部导航的效果,可以参考官方文档 uniapp添加tabBar官方文档地址: uniapp.dcloud.net.cn/collocation...

下面将下图为示例写部分代码案例: 在pages.json写上tabBar 并在List定义好每个页面与页面展示图标,以及不同选中时图标的效果,就可以实现下面页面展示的样式:

案例代码: 注意导航页的图标和页面都必须在根路径下面,因此不能使用网络地址,或分包下的图片和页面。

 "tabBar": {
      "color": "#bababa",
      "selectedColor": "#000000",
      "borderStyle": "black",
      "backgroundColor": "#ffffff",
      "list": [
          {
              "pagePath": "pages/tabbar/index/index",
              "iconPath": "static/images/common/shouye.png",
              "selectedIconPath": "static/images/common/shouye-xz.png",
              "text": "首页"
          },
          {
              "pagePath": "pages/talent/index",
              "iconPath": "static/images/common/task.png",
              "selectedIconPath": "static/images/common/task_d.png",
              "text": "达人任务"
          },
          {
              "pagePath": "pages/tabbar/facilitator/facilitator",
              "iconPath": "static/images/common/facilitator.png",
              "selectedIconPath": "static/images/common/facilitator_d.png",
              "text": "服务商"
          },
          {
              "pagePath": "pages/aiTools/aiTools",
              "iconPath": "static/images/common/aitools.png",
              "selectedIconPath": "static/images/common/aitools_d.png",
              "text": "创作助手"
          },
          {
              "pagePath": "pages/tabbar/info/info",
              "iconPath": "static/images/common/info.png",
              "selectedIconPath": "static/images/common/info_d.png",
              "text": "我的"
          }
      ]
     },

自定义tabBar

梳理业务:

  1. 去除pages.json写上tabBar注释相关代码;
  2. 通过uni.hideTabBar();隐藏uniapp自带的tabBar;
  3. 自定义tabBar组件,实现页面相关逻辑;
  4. 在相关页面引入该组件;
  5. 根据在页面的onShow方法,当页面显示通过$ref,调用相关逻辑,判断需要显示的底部tabBar按钮和样式。

下面将以下图为案例写相关逻辑:

  1. 去除pages.json写上tabBar注释相关代码,图上写了一个list.pagePath 主要的作用是占位,没别的意义

2.封装tabBar.vue组件

ps:我在components\tabbar\tabbar.vue路径下封装tabBar.vue组件,其他的小伙伴可以根据自己的页面需求写在对应位置,例如想实现首页点击进入不同的分包和页面展示不同的tabBar,那么可以根据自己的需求进行调整。

<template>
	<view class="tabbar">
		<view class="tabbar-item" v-for="(item, index) in list" :key="index" @click="changeTab(index)">

			<template v-if="index != 2">
				<view class="select" v-if="current == index">
					<view>
						<view class="i-t position">
							<image class="img imgactive" mode="widthFix" :src="item.selectedIconPath"
								v-if="current == index">
							</image>
							<image class="img" mode="widthFix" :src="item.iconPath" v-else></image>
							<view class="text active" v-if="current == index">{{ item.text }}</view>
							<view class="text" v-else>{{ item.text }}</view>
						</view>
					</view>
				</view>
				<view v-else>
					<view class="i-t">
						<image class="img" mode="widthFix" :src="item.selectedIconPath" v-if="current == index"></image>
						<image class="img" mode="widthFix" :src="item.iconPath" v-else></image>
						<view class="text active" v-if="current == index">{{ item.text }}</view>
						<view class="text" v-else>{{ item.text }}</view>
					</view>
				</view>
			</template>
			<!-- 下面是为了解决自定义业务需求,如果is_identity = 3则显示中间的加号,不然显示服务商 -->
			<template v-else>
				<view class="i-t" v-if="is_identity == 3" >
					<image class="img" mode="widthFix" :src="urladdTask" style="width: 140rpx;height: 140rpx;position: absolute;top: -50rpx;"></image>
				</view>
				<view class="i-t" v-else>
					<view class="select" v-if="current == index">
						<view>
							<view class="i-t position">
								<image class="img imgactive" mode="widthFix" :src="item.selectedIconPath"
									v-if="current == index">
								</image>
								<image class="img" mode="widthFix" :src="item.iconPath" v-else></image>
								<view class="text active" v-if="current == index">{{ item.text }}</view>
								<view class="text" v-else>{{ item.text }}</view>
							</view>
						</view>
					</view>
					<view v-else>
						<view class="i-t">
							<image class="img" mode="widthFix" :src="item.selectedIconPath" v-if="current == index">
							</image>
							<image class="img" mode="widthFix" :src="item.iconPath" v-else></image>
							<view class="text active" v-if="current == index">{{ item.text }}</view>
							<view class="text" v-else>{{ item.text }}</view>
						</view>
					</view>
				</view>
			</template>






		</view>
	</view>
</template>

<script>
//引入图片资源
import addTask from '../../static/images/common/addTask.png'
export default {
	name: "tabbar",
	props: ['current'],
	data() {
		return {
			urladdTask: addTask,
			is_identity: 0,
                        // TODO: 下面list则是你页面上具体展示的底部按钮,根据你的需求和页面进行调整
			list: [
				{
					"pagePath": "pages/tabbar/index/index",
					"iconPath": "../../static/images/common/shouye.png",
					"selectedIconPath": "../../static/images/common/shouye-xz.png",
					"text": "首页"
				},
				{
					"pagePath": "pages/talent/index",
					"iconPath": "../../static/images/common/task.png",
					"selectedIconPath": "../../static/images/common/task_d.png",
					"text": "达人任务"
				},
				{
					"pagePath": "pages/tabbar/facilitator/facilitator",
					"iconPath": "../../static/images/common/facilitator.png",
					"selectedIconPath": "../../static/images/common/facilitator_d.png",
					"text": "服务商"
				},
				{
					"pagePath": "pages/aiTools/aiTools",
					"iconPath": "../../static/images/common/aitools.png",
					"selectedIconPath": "../../static/images/common/aitools_d.png",
					"text": "创作助手"
				},
				{
					"pagePath": "pages/tabbar/info/info",
					"iconPath": "../../static/images/common/info.png",
					"selectedIconPath": "../../static/images/common/info_d.png",
					"text": "我的"
				}
			]

		}
	},

	created() {
		//隐藏tabbar
		uni.hideTabBar();
	},
	mounted() {
	},
	methods: {
		changeTab(e) {
			uni.switchTab({
				url: '/' + this.list[e].pagePath,
			})
		}
	}


}

</script>

<style>
.tabbar {
	font-size: 1.5vh;
	position: fixed;
	left: 0;
	bottom: 0;
	z-index: 99;
	width: 100%;
	height: 6vh;
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	align-items: center;
	justify-content: space-around;
	background-color: #fff;
	padding: 20rpx 0;
}

.tabbar-item {
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	position: relative;
}
.img {
	height: 3vh;
	width: 2.5vh;
}
.text {
	text-align: center;
	color: #CACACA;
}
.i-t {
	display: flex;
	flex-direction: column;
	justify-items: center;
	align-items: center;
}
.select {
	position: relative;
}

.text.active {
	color: red;
}
.index0 {
	width: 80rpx;
	height: 80rpx;
}
</style>
  1. 组件封装完毕需要在对应的页面中引入该组件 例如 下面index.vue
   </template>
   	</view>
                   //current则表示选中的状态,例如当前是首页则current为0,如果是第三页则current=2
   		<tabbar current="0" ref="mytabbar"></tabbar>
   	</view>
   </template>

   <script>

   import tabbar from '@/components/tabbar/tabbar.vue';
   export default {
       components: {
           tabbar
       },
   }
  1. 在tabBar.vue组件写上相关页面判断,例如不同的角色则显示不同的按钮,或不同样式。 tabBar.vue组件中的methods添加一个init函数:
       init() {
           //获取用户信息
           let userinfo = uni.getStorageSync('user');
           // 获取角色状态,赋值给is_identity
           if (userinfo) {
               this.is_identity = userinfo?.identity;
           }
           //...其他调接口等业务处理
       }

在第三步的index.vue页面中,引入的tabbar组件定义了一个ref="mytabbar",可以通过this.$refs.tabBar.init();的方式来调用tabBar.vue组件中的methods的init函数。 例如在index.vue组件下的onShow方法下,当页面显示时候执行tabBar.vue组件中的methods的init函数

       async onShow() {
               await this.getuserinfo();
               //其他业务
       },
相关推荐
用户48062260414153 小时前
使用uniapp开发微信小程序-框架搭建
微信小程序·uni-app
TttHhhYy5 小时前
uniapp+vue开发app,蓝牙连接,蓝牙接收文件保存到手机特定文件夹,从手机特定目录(可自定义),读取文件内容,这篇首先说如何读取,手机目录如何寻找
开发语言·前端·javascript·vue.js·uni-app
Funky_oaNiu5 小时前
uniapp实现按钮防重复点击(防抖)完整解决方案
uni-app
原克技术5 小时前
uniapp验证码
uni-app
web150850966411 天前
在uniapp Vue3版本中如何解决webH5网页浏览器跨域的问题
前端·uni-app
何极光1 天前
uniapp小程序样式穿透
前端·小程序·uni-app
User_undefined2 天前
uniapp Native.js 调用安卓arr原生service
android·javascript·uni-app
流氓也是种气质 _Cookie2 天前
uniapp blob格式转换为video .mp4文件使用ffmpeg工具
ffmpeg·uni-app
爱笑的眼睛112 天前
uniapp 极速上手鸿蒙开发
华为·uni-app·harmonyos
小刘鸭!2 天前
notepad++快捷键-多行编辑中如何使所有行的光标都向后移动一个单词的长度(每行单词长度不一定一致)
前端·javascript·notepad++