uniapp 小程序根据权限动态生成 tabbar

  • Post author:
  • Post category:uniapp




引言

开发小程序时,有些项目会遇到需要根据角色权限去动态生成 tabbar 的情况,因此就需要开发者自己来定义 tabbar 组件,tabbar 的数量不超过5个



封装 tabbar 组件



1.在 components 目录下定义组件

<template>
	<view class="uni-tabbar">
		<view class="uni-tabbar-item" v-for="(item, index) in tabbar" :key="index" @tap="changeTab(item)">
			<view class="uni-tabbar-bd">
				<view class="uni-tabbar-icon">
					<image v-if="item.pagePath == pagePath" class="icon-img" mode="aspectFit" :src="validateHttp(item.selectedIconPath)" />
					<image v-else class="icon-img" mode="aspectFit" :src="validateHttp(item.iconPath)" />
				</view>
			</view>
			<view class="uni-tabbar-label" :class="{ active: item.pagePath === pagePath }">{{ item.text }}</view>
		</view>
	</view>
</template>

<script>
import { mapGetters } from 'vuex';
import { isHttpOrHttps } from '@/utils/replace.js';
export default {
	props: {
		// 当前页面路径
		pagePath: {
			type: String,
			required: true
		},
		// tabbar 底部导航栏数据
		tabbar: {
			type: Array,
			required: true
		}
	},
	computed: {
		...mapGetters(['tabBarList'])
	},
	// watch: {
	// 	pagePath: {
	// 		handler(val) {
	// 			// console.log('pagePath监听===val', val);
	// 		},
	// 		immediate: true
	// 	}
	// },
	methods: {
		// 检验拼接url地址
		validateHttp(url) {
			return isHttpOrHttps(url);
		},
		changeTab(item) {
			this.page = item.pagePath;
			uni.switchTab({ url: this.page });
			this.$emit('onTabTap');
		}
	}
};
</script>

<style lang="scss" scoped>
.uni-tabbar {
	position: fixed;
	bottom: 0;
	z-index: 50;
	width: 100%;
	display: flex;
	justify-content: space-around;
	padding-bottom: calc(24rpx + constant(safe-area-inset-bottom));
	padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
	box-sizing: border-box;
	border-top: solid 1rpx #dddddd;
	background-color: #fff;

	.uni-tabbar-item {
		width: 25%;
		height: 100rpx;
		display: flex;
		flex-direction: column;
		justify-content: space-around;
		align-items: center;
	}

	.uni-tabbar-icon {
		height: 64rpx;
	}

	.icon {
		display: inline-block;
	}

	.uni-tabbar-label {
		line-height: 24rpx;
		font-size: $font-size-sm;
		color: $color;

		&.active {
			font-weight: 600;
		}
	}

	.icon-img {
		width: 64rpx;
		height: 64rpx;
	}
}
</style>



2. 根据权限定义 tabbar 数据

let BUYER = [

	{
		text: "推荐",
		pagePath: '/pages/common/recommend/index',
		iconPath: "wxapp-img/icon/ic_tuijian.png",
		selectedIconPath: "wxapp-img/icon/ic_tuijian_n.png",
	},
	{
		text: "关注",
		pagePath: '/pages/common/brandFollow/index',
		iconPath: "wxapp-img/icon/ic_guanuzhu.png",
		selectedIconPath: "wxapp-img/icon/ic_guajnzhu_n.png",
	},
	{
		text: "订单",
		pagePath: '/pages/buyer/order/index',
		iconPath: "wxapp-img/icon/ic_dingdan.png",
		selectedIconPath: "wxapp-img/icon/ic_dingdan_n.png",
	},
	{
		text: "我的",
		pagePath: '/pages/common/mine/index',
		iconPath: "wxapp-img/icon/ic_wode.png",
		selectedIconPath: "wxapp-img/icon/ic_wode_n.png",
	},
]

let SHOP_MANAGER = [

	{
		text: "推荐",
		pagePath: '/pages/common/recommend/index',
		iconPath: "wxapp-img/icon/ic_tuijian.png",
		selectedIconPath: "wxapp-img/icon/ic_tuijian_n.png",
	},
	{
		text: "关注",
		pagePath: '/pages/common/brandFollow/index',
		iconPath: "wxapp-img/icon/ic_guanuzhu.png",
		selectedIconPath: "wxapp-img/icon/ic_guajnzhu_n.png",
	},
	{
		text: "采购车",
		pagePath: '/pages/manager/car/index',
		iconPath: "wxapp-img/icon/ic_caigouche.png",
		selectedIconPath: "wxapp-img/icon/ic_caigoouche_n.png",
	},
	{
		text: "我的",
		pagePath: '/pages/common/mine/index',
		iconPath: "wxapp-img/icon/ic_wode.png",
		selectedIconPath: "wxapp-img/icon/ic_wode_n.png",
	},
]


export default {
	BUYER,
	SHOP_MANAGER
}



3.vuex 中获取角色的 tabbar 数据

// modules/tabBar.js
import tabbar from '@/utils/tabbar.js'

const tabBar = {
	state: {
		role: '',
		tabBarList: [],
	},
	mutations: {
		setRole(state, role) {
			state.role = role;
			state.tabBarList = tabbar[role];
		}
	},
}

export default tabBar


// getters.js
const getters = {
	tabBarList: state => state.tabBar.tabBarList,
	role: state => state.tabBar.role
}
export default getters

// index.js
import Vue from 'vue';
import Vuex from 'vuex';
import tabBar from './modules/tabBar.js'
import getters from './getters.js'

Vue.use(Vuex);

const store = new Vuex.Store({
	modules: {
		tabBar
	},
	getters
})
export default store;




4.在接口返回角色身份或者权限数据时,设置 vuex 的 tabBarList



5.在需要的页面都引入组件

...
<tab-bar :tabbar="tabBarList" :pagePath="routerPath"/>
...

<script>
import { mapGetters } from 'vuex';
import TabBar from '@/components/TabBar/index.vue';
export default {
	data() {
		return {
			// 获取当前页面路径
			routerPath: '/' + this.$mp.page.route,
		};
	},
	computed: {
		...mapGetters(['tabBarList'])
	},
	components: {
		TabBar
	},
	onShow() {
		// 隐藏原生tabbar
		uni.hideTabBar({});
	},
}
</script>



6.在 App.vue 中添加操作

	onShow() {
		// 隐藏原生tabbar
		uni.hideTabBar({});
	},



7. pages.json 添加 tabbar 数据

// 根据权限路径去重,把所有的 tabbar 路径添加进去,记得不得超过5个
	"tabBar": {
		"list": [{
				"pagePath": "pages/common/recommend/index"
			},
			{
				"pagePath": "pages/common/brandFollow/index"
			},
			{
				"pagePath": "pages/buyer/order/index"
			},
			{
				"pagePath": "pages/common/mine/index"
			},
			{
				"pagePath": "pages/manager/car/index"
			}
		]
	},

此方法也是通过网上资料查找和我项目自身的情况改造的,如有错误,欢迎各位指出!



最后,记得 pages.json 里面的 tabBar 数据不能超5个,如果一定会超5个,就需要完全自定义,跳转的页面是 tabbar 页面,就只能使用 uni.reLaunch() 方法,并且不需要再 pages.json 里面的 tabBar 配置路径!!!



版权声明:本文为m0_64344940原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。