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

uniapp多角色tabbar切换与登录验证实现
文章介绍了如何在uniapp中,根据用户登录身份动态切换tabbar页面,包括vue2和vue3版本的实现步骤,以及处理登录验证和tabbar颜色闪烁问题的解决方案。

目录

一、背景

源码地址:包含vue2和vue3版本cheinlu/tabBar_demo_vue

二、效果展示

三、前置工作

四、创建tabbar组件

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

六、问题拓展


一、背景

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

备注:本次示例为vue2版本,vue3版本源码可查看以下地址👇

完整代码地址(包含vue2和vue3版本)👉: cheinlu/tabBar_demo_vue

二、效果展示

2.1、角色1:admin账号登录效果

用户名:admin    密码:123456

2.2、角色2:tom账户登录效果

用户名:tom    密码:123456

三、前置工作

3.1、将登录页面作为用户进入小程序展示的第一个页面,pages.json文件中的pages数组第一个设为login页面👇

3.2、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/warn/warn",
            "style" :                                                                                    
            {
                "navigationBarTitleText": "告警",
                "enablePullDownRefresh": false
            }
            
        }
		,{
            "path" : "pages/my/my",
            "style" :                                                                                    
            {
                "navigationBarTitleText": "我的",
                "enablePullDownRefresh": false
            }
            
        }
    ],
	"globalStyle": {
		"navigationBarTextStyle": "black",
		"navigationBarTitleText": "uni-app",
		"navigationBarBackgroundColor": "#F8F8F8",
		"backgroundColor": "#F8F8F8"
	},
	"uniIdRouter": {},
	"tabBar": {
		"list": [
			{
			    "pagePath": "pages/index/index"
			},
			{
				"pagePath": "pages/warn/warn"
			},
			{
				"pagePath": "pages/my/my"
			}
		]
	}
}

四、创建tabbar组件

4.1、第一步:在项目中创建components文件夹,并在文件夹下创建tabbar组件👇

tabbar组件具体代码如下:

<template>
    <view class="tab">
         <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 {
        props: {
            selectedIndex: { // 当前选中的tab index
                default: 0
            },
        },
        data() {
            return {
                color: "#666666",
                selectedColor: "#00BAB2",
                list: [],
                currentIndex:0,
            }
        },
        created() {
            this.currentIndex = this.selectedIndex;
            
            let _this = this
            
            if (uni.getStorageSync('identify') == 'tom') {
                //角色1
                _this.list = [{
                        "pagePath": "/pages/index/index",
                        "iconPath": "/static/tab/home.png",
                        "selectedIconPath": "/static/tab/home_active.png",
                        "text": "首页"
                    },
                    {
                        "pagePath": "/pages/my/my",
                        "iconPath": "/static/tab/my.png",
                        "selectedIconPath": "/static/tab/my_active.png",
                        "text": "我的"
                    }
                ]
            } else {
                //角色2
                _this.list = [{
                        "pagePath": "/pages/index/index",
                        "iconPath": "/static/tab/home.png",
                        "selectedIconPath": "/static/tab/home_active.png",
                        "text": "首页"
                    },
                    {
                       "pagePath": "/pages/warn/warn",
                       "iconPath": "/static/tab/warn.png",
                       "selectedIconPath": "/static/tab/warn_active.png",
                       "text": "告警"
                    },
                    {
                        "pagePath": "/pages/my/my",
                        "iconPath": "/static/tab/my.png",
                        "selectedIconPath": "/static/tab/my_active.png",
                        "text": "我的"
                    }
                ]
            }
        },
        methods: {
            switchTab(item, index) {
                this.currentIndex = index;
                let url = item.pagePath;
                uni.redirectTo({url:url})
                
            }
        }
    }
</script>

<style lang="scss">
    .tab {
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        height: 100rpx;
        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: 60rpx;
                height: 60rpx;
            }
            .tab_text {
                font-size: 30rpx;
                margin-top: 9rpx;
            }
        }
    }
</style>

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

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

4.2、第二步: 在main.js文件中将自定义的tabBar定义为全局组件

//⭐⭐ main.js 文件
import tabBar from "@/components/tabbar/tabbar.vue"
Vue.component('tabBar',tabBar)

4.3、第三步:在需要使用的页面引入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>

4.4、第四步:隐藏pages.json里配置的导航栏,使用封装的tabbar组件,在需要引入tabbar组件的页面进行配置

//如 warn 页面👇 index 和 my 页面也是同样的设置
<script>
  export default {
    onShow() {
       //⭐隐藏pages.json里配置的导航栏,使用封装的tabbar组件
      uni.hideTabBar({
        animation:false
     })
    }
  }
</script>

五、登录页面根据不同身份进行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>

六、问题拓展

6.1、问题:当是角色1时,点击tabbar我的页面文字和图标造成颜色闪烁

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

6.3、解决:在传递 selectedIndex<tabBar> 组件时进行判断,并确保它不会超出角色1 tab 的索引范围

6.4、重新修改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>

PS:如果对你有帮助的话,请给个赞,有问题欢迎大家在评论区讨论。ღ( ´・ᴗ・` )  ღ( ´・ᴗ・` ) 

最后:👏👏😊😊😊👍👍 

<think> 首先,用户的问题是:"我想查找uniapp使用redirectTo跳转后底部导航栏tabbar不显示的解决方案 请问uniapp使用redirectTo跳转后底部导航栏tabbar不显示的解决办法"。所以,我需要提供解决这个问题的方案。 系统指令要求: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题,保证真实可靠。 用户提供了几个引用,我需要参考它们: - 引用[1]:讨论了一个统一的导航方法,使用redirectTo并在失败时尝试switchTab。 - 引用[2]:关于uni-apptabBar使用。 - 引用[3]:解决自定义tabbar页面刷新导致的闪烁问题,提到了优化样式和性能。 - 引用[4]:关于uni-app中的导航跳转。 用户的具体问题是:在使用uni.redirectTo跳转后,底部导航栏tabbar不显示。这可能是由于redirectTo方法的行为导致的。 在uni-app中,uni.redirectTo用于关闭当前页面并跳转到新页面,而tabBar页面通常需要使用uni.switchTab来跳转,因为switchTab专门用于切换tabBar页面。如果使用redirectTo跳转到一个tabBar页面,tabBar可能不会显示,因为redirectTo不适合tabBar页面。 解决方案: 1. 确保跳转到tabBar页面时使用uni.switchTab而不是uni.redirectTo。 2. 如果需要统一处理导航,可以在失败时尝试switchTab,如引用[1]所示。 3. 如果tabBar是自定义的,检查自定义组件的实现,确保样式和性能优化,如引用[3]提到的position: fixed等。 结构化回答: - 先解释问题原因。 - 提供解决方案步骤。 - 给出代码示例。 - 添加相关引用。 - 最后生成相关问题。 回答使用中文。 生成相关问题: - 基于主题,生成2-3个相关问题。 最终回答结构: 1. 问题分析:为什么使用redirectTo后tabbar不显示? 2. 解决方案:提供步骤和代码。 3. 代码优化:参考引用,添加性能考量。 4. 引用标识。 5. 相关问题。 </think>### Uniapp 使用 redirectTo 跳转后底部导航栏 TabBar 不显示的解决方案 在 Uniapp 中,使用 `uni.redirectTo` 方法跳转页面后,底部导航栏 TabBar 不显示是一个常见问题。这通常是因为 `redirectTo` 的设计机制导致:它 **关闭当前页面并跳转至新页面**,但 TabBar 页面(即通过 `pages.json` 配置为 `tabBar` 的页面)必须使用 `uni.switchTab` 方法跳转才能正常显示 TabBar。否则,系统会将目标页面视为普通页面而非 TabBar 页面,从而隐藏 TabBar[^1][^2]。以下是详细解决步骤: #### 问题原因分析 - **`redirectTo` 的限制**:`uni.redirectTo` 适用于非 TabBar 页面间的跳转,它不会触发 TabBar 的渲染逻辑。 - **TabBar 页面的特殊要求**:只有通过 `uni.switchTab` 跳转时,Uniapp 才会识别并显示底部导航栏- **常见触发场景**: - 在普通页面使用 `uni.redirectTo` 尝试跳转至 TabBar 页面。 - 自定义 TabBar 实现时未正确处理跳转逻辑[^3]。 #### 解决方案步骤 1. **检查跳转目标是否为 TabBar 页面**: - 在 `pages.json` 中确认目标页面是否在 `tabBar.list` 中配置。例如: ```json // pages.json 配置 "tabBar": { "list": [ {"pagePath": "pages/index/index", "text": "首页"}, {"pagePath": "pages/user/user", "text": "用户中心"} // 此为 TabBar 页面 ] } ``` 2. **替换 `redirectTo` 为 `switchTab`**: - **直接修复**:若目标页面是 TabBar 页面,必须使用 `uni.switchTab` 代替 `uni.redirectTo`。 ```javascript // 错误示例(导致 TabBar 不显示) uni.redirectTo({ url: '/pages/user/user' }); // 正确示例(使用 switchTab) uni.switchTab({ url: '/pages/user/user' }); // TabBar 正常显示[^1][^2] ``` 3. **统一导航方法处理兼容性**(参考引用[1]): - 如果需在代码中统一处理跳转(例如兼容普通页面和 TabBar 页面),可封装一个导航函数: ```javascript // 统一导航方法 navigateTo(path) { uni.redirectTo({ url: path, fail: (err) => { // 若 redirectTo 失败(如目标是 TabBar 页面),改用 switchTab uni.switchTab({ url: path, success: () => console.log('跳转至 TabBar 页面成功'), fail: (err) => console.error('跳转失败', err) }); } }); } ``` - **说明**:此方法先尝试 `redirectTo`,失败时(通常是目标为 TabBar 页面)自动切换至 `switchTab`[^1]。 4. **自定义 TabBar 的优化**(参考引用[3]): - 若使用了自定义 TabBar 组件,需确保样式和性能优化,避免跳转后闪烁或布局问题: - 在组件样式中添加: ```css /* 自定义 TabBar 组件样式 */ .custom-tabbar { position: fixed; bottom: 0; z-index: 999; -webkit-transform-style: preserve-3d; /* 开启硬件加速 */ -webkit-backface-visibility: hidden; /* 避免闪烁 */ } ``` - 在跳转逻辑中,手动调用 TabBar 的更新方法,确保状态同步。 5. **调试与验证**: - 在开发者工具中检查控制台是否有错误日志(如路径错误)。 - 使用真机测试,确保 TabBar 在 iOS 和 Android 上均正常显示。 #### 代码优化与性能考量 - **减少不必要的跳转**:频繁使用 `redirectTo` 可能导致页面栈溢出,优先使用 `switchTab` 或 `navigateTo`。 - **自定义 TabBar 性能**:开启硬件加速(如引用[3]所述)可提升渲染效率,避免跳转卡顿[^3]。 - **最佳实践**:在 `pages.json` 中明确区分 TabBar 和非 TabBar 页面,避免混用跳转方法。 通过以上步骤,可有效解决 TabBar 不显示的问题。若仍有异常,请检查 TabBar 配置路径是否正确或提供更多代码细节[^1][^2][^3]。
评论 44
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值