uniapp 实现不同用户展示不同的tabbar(底部导航栏)

最近在做一个uniapp开发的小程序遇到一个需求,希望不同用户登录后展示不同的tabbar页面,但是uniapp项目中的pages.json是只有一个list数组的,并且是不能写成动态效果,为了实现这个需求,便自定义了tabbar组件。

一、基础配置

1. 配置tabbar

pages.json配置tabbar的基本路径(只需路径即可)

{
	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
		{
		    "path" : "pages/login/login",
		    "style" :                                                                                    
		    {
		        "navigationBarTitleText": "",
		        "enablePullDownRefresh": false
		    }
		    
		},
    {
			"path": "pages/index/index",
			"style": {
				"navigationBarTitleText": ""
			}
		}
	    ,{
            "path" : "pages/my/my",
            "style" :                                                                                    
            {
                "navigationBarTitleText": "",
                "enablePullDownRefresh": false
            }
            
        }
        ,{
            "path" : "pages/warn/warn",
            "style" :                                                                                    
            {
                "navigationBarTitleText": "",
                "enablePullDownRefresh": false
            }
            
        }
        
    ],
	"globalStyle": {
		"navigationBarTextStyle": "black",
		"navigationBarTitleText": "uni-app",
		"navigationBarBackgroundColor": "#F8F8F8",
		"backgroundColor": "#F8F8F8"
	},
	"uniIdRouter": {},
  "tabBar": {
    "color": "#999",
    "selectedColor": "#0aa671",
    "borderStyle": "white",
    "list": [
        {
            "pagePath": "pages/index/index"
        },
        {
            "pagePath": "pages/warn/warn"
        },
        {
            "pagePath": "pages/my/my"
        }
    ]
  }
}
2. 创建tabbar组件
  • 第一步:在项目中创建components文件夹,并在文件夹下创建tabbar组件👇
<template>
  <!--自定义动态tarbar 在需要展示tarbar的页面引入即可
    <tabBar selectedIndex = 0></tabBar>

    第一种:
     * 根据身份判断 动态显示tarbar内容

    第二种:
     * 有具体的页面传递需要动态显示的tarbar,也是支持的

     设计思路:tarbar组件根据页面传递的动态内容显示不同tarbar效果
  -->
  <view class="tab">
    <!--    <image src="/static/images/tabbar/index.png"></image>-->
    <view v-for="(item,index) in list" :key="index" class="tab-item" @click="switchTab(item, index)">
      <image class="tab_img" :src="currentIndex == index ? item.selectedIconPath : item.iconPath"></image>
      <view class="tab_text" :style="{color: currentIndex == index ? selectedColor : color}">{{ item.text }}</view>
    </view>
  </view>
</template>

<script>
export default {
  name: "rarbar",
  props: {
    selectedIndex: { // 当前选中的tab index
      default: 0
    },
  },
  data() {
    return {
      color: "#666666",
      selectedColor: "#00BAB2",
      list: [],
      currentIndex: 0,
    }
  },
  created() {
    this.currentIndex = this.selectedIndex;

    let _this = this
    /**
     * 第一种:
     * 根据身份判断 动态显示tarbar内容
     * 登录从后端获取值设置值
     */
    if (uni.getStorageSync('identify') == 'tom') {
      //角色1
      _this.list = [{
        "pagePath": "/pages/sub_eventOrder/toDoTasks/index",
        "iconPath": "/static/images/tabbar/index.png",
        "selectedIconPath": "/static/images/tabbar/index_active.png",
        "text": "首页"
      },
        {
          "pagePath": "/pages/main",
          "iconPath": "/static/images/tabbar/know.png",
          "selectedIconPath": "/static/images/tabbar/know_active.png",
          "text": "知识分享"
        }
      ]
    } else {
      //角色2 item.selectedIconPath : item.iconPath"
      _this.list = [{
        "pagePath": "/pages/index",
        "iconPath": "/static/images/tabbar/index.png",
        "selectedIconPath": "/static/images/tabbar/index_active.png",
        "text": "首页"
      },
        {
          "pagePath": "/pages/mine/index",
          "iconPath": "/static/images/tabbar/me.png",
          "selectedIconPath": "/static/images/tabbar/me_active.png",
          "text": "我的"
        }
      ]
    }

    /**
     * 第二种:
     * 有具体的页面传递需要动态显示的tarbar,也是支持的
     */

  },
  methods: {
    switchTab(item, index) {
      this.currentIndex = index;
      let url = item.pagePath;
      console.log("url", url)

      // 跳转tarbar 使用这种方式
      // this.$tab.switchTab( url)

      // 跳转普通页面使用郑重方式
      this.$tab.redirectTo(url)
    }
  }
}
</script>

<style lang="scss">
.tab {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 50px;
  background: white;
  display: flex;
  justify-content: center;
  align-items: center;
  padding-bottom: env(safe-area-inset-bottom); // 适配iphoneX的底部

  .tab-item {
    flex: 1;
    text-align: center;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;

    .tab_img {
      width: 20px;
      height: 20px;
    }

    .tab_text {
      font-size: 10px;
      margin-top: 5px;
      margin-bottom: 2px;
    }
  }
}
</style>

注意:👉 跳转路径:pagePath以/开头

说明:tab_img可以修改图标大小,tab_text可以修改文字大小

  • 第二步: 在main.js文件中将自定义的tabBar定义为全局组件
//⭐⭐ main.js 文件
import tabBar from "@/components/tabbar/tabbar.vue"
Vue.component('tabBar',tabBar)
  • 第三步:在需要使用的页面引入tabbar组件
//如 index页面👇
<template>
  <view>
    告警
    <tabBar selectedIndex = 0></tabBar>
  </view>
</template>
 
//如 warn 页面👇
<template>
  <view>
    告警
    <tabBar selectedIndex = 1></tabBar>
  </view>
</template>
 
 
//如 my 页面👇
<template>
  <view>
    告警
    <tabBar selectedIndex = 2></tabBar>
  </view>
</template>
  • 第四步:隐藏pages.json里配置的导航栏,使用封装的tabbar组件,在需要引入tabbar组件的页面进行配置
//如 warn 页面👇 index 和 my 页面也是同样的设置
<script>
  export default {
    onShow() {
       //⭐隐藏pages.json里配置的导航栏,使用封装的tabbar组件
      uni.hideTabBar({
        animation:false
     })
    }
  }
</script>
3. 动态跳转逻辑

登录页面根据不同身份进行tabbar切换逻辑

//登录 login 页面👇
<template>
<view class="container">
<view class="form-group">
<text>用户名:</text>
<input v-model="username" type="text" placeholder="请输入用户名"></input>
</view>
 
<view class="form-group">
  <view style="margin-left: 30rpx;"></view>
<text>密码:</text>
<input v-model="password" type="password" placeholder="请输入密码"></input>
</view>
<view class="btn-login">
<button @click="login">登录</button>
</view>
</view>
</template>
 
<script>
export default {
  data() {
    return {
      //页面上设置的默认账户admin,密码123456
      username: 'admin',
      password: '123456'
    };
  },
  onShow() {
    uni.clearStorageSync('identify')
  },
  methods: {
    login() {
      const username = this.username;
      const password = this.password;
      let identify = '';
 
      // 根据用户名和密码来确定身份
      if (username === 'tom' && password === '123456') {
        identify = 'tom';
      } else if (username === 'admin' && password === '123456') {
        identify = 'admin';
      } else {
        // 用户名或密码错误
        console.log('用户名或密码错误');
        return;
      }
      //本地存储
      uni.setStorageSync('identify', identify);
 
      // 跳转到首页
      uni.switchTab({
        url: '/pages/index/index'
      });
    }
  }
};
</script>
 
<style scoped>
.container {
padding: 30rpx;
}
 
.form-group {
  display: flex;
  align-items: center;
  justify-content: center;
margin-bottom: 30rpx;
}
input{
  border: 1rpx solid #00BAB2;
  padding: 10rpx;
}
button {
background-color: #00BAB2;
color: white;
border: none;
border-radius: 20rpx;
}
</style>

二、问题拓展
2.1. 问题一
当是角色1时,点击tabbar我的页面文字和图标造成颜色闪烁

2.2. 原因解析
角色1是有两个tabbar ,“我的”页面对应的index值是1,而selectedIndex 被设置为超出角色1 tab 的索引范围。在这种情况下,currentIndex 的默认值为0,而将 selectedIndex 设置为2 会导致 currentIndex 与实际选中的 tab 不一致,进而导致文字和图标显示颜色发生闪烁。

2.3.解决方案
在传递 selectedIndex 给 组件时进行判断,并确保它不会超出角色1 tab 的索引范围

  • 重新修改my页面
//👇 my 页面
<template>
  <view>
    我的
   <tabBar :selectedIndex="selectedTabIndex"></tabBar>
 
  </view>
</template>
 
<script>
  export default {
    computed: {
      //判断是什么角色
      selectedTabIndex() {
        return uni.getStorageSync('identify') === 'tom' ? 1 : 2;
      }
    },
    onShow() {
      uni.hideTabBar({
        animation:false
     })
    },
   
  }
</script>

项目地址:CODING | 一站式软件研发管理平台

### 实现 UniApp 应用中自定义底部导航栏页面切换 #### 一、配置 `manifest.json` 文件 为了使自定义 tabBar 生效,需先在项目的根目录下的 `manifest.json` 配置文件里设置 `"usingComponents"` 字段为 true 并指定 tabBar 的路径[^1]。 ```json { "appid": "", "projectname": "yourProjectName", ... "app-plus": { "usingComponents": true, "tabBar": { "list": [ { "pagePath": "pages/index/index", "text": "首页" }, ... ] } } } ``` #### 二、创建自定义组件 新建一个名为 `custom-tab-bar.vue` 组件用于构建自定义的 tabBar 结构。此部分可以根据实际需求调整布局设计以及交互逻辑[^2]。 ```html <template> <view class="custom-tab-bar"> <!-- 这里放置各个 tab-item --> <block v-for="(item, index) in items" :key="index"> <view @click="changeItem(item)" :class="[currentIndex === index ? 'active' : '', 'tab-item']">{{ item.text }}</view> </block> </view> </template> <script> export default { data() { return { currentIndex: 0, items: [ { text: '首页', path: '/pages/index/index' }, // 添加更多项... ] }; }, methods: { changeItem(item) { uni.switchTab({ url: item.path }); } } }; </script> <style scoped lang="scss"> .custom-tab-bar { display: flex; justify-content: space-around; .tab-item { padding: 15px; font-size: 14px; &.active { color: red; /* 可替换为你想要的颜色 */ } } } </style> ``` #### 三、处理页面加载顺序问题 为了避免首次进入应用时可能出现的内容闪动现象,在 `pages.json` 中添加一个新的启动页作为过渡界面[^3]。 ```json { "pages":[ {"path":"pages/splash/splash"},// 启动页 {"path":"pages/index/index"} ], "globalStyle":{ "navigationBarTitleText":"WeChat" } } ```
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王旭晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值