Uniapp 自定义 Tabbar 实现教程
Uniapp 自定义 Tabbar 实现教程
- 1. 简介
- 2. 实现步骤
- 2.1 创建自定义 Tabbar 组件
- 2.2 配置 pages.json
- 2.3 在 App.vue 中引入组件
- 3. 实现过程中的关键点
- 3.1 路由映射
- 3.2 样式设计
- 3.3 图标处理
- 4. 常见问题及解决方案
- 4.1 页面跳转问题
- 4.2 样式适配问题
- 4.3 性能优化
- 5. 扩展功能
- 5.1 添加徽标
- 5.2 添加动画效果
- 6. 总结
1. 简介
在 Uniapp 开发中,自定义 Tabbar 是一个常见的需求。本教程将详细介绍如何实现一个美观且功能完整的自定义 Tabbar,并分享在实现过程中可能遇到的问题和解决方案。
2. 实现步骤
2.1 创建自定义 Tabbar 组件
首先,我们需要创建一个自定义的 Tabbar 组件。以下是完整的实现代码:
<template><!-- 自定义 Tabbar 容器 --><view class="custom-tabbar"><!-- 遍历 tabList 生成 Tabbar 项 --><view v-for="(item, index) in tabList" :key="index" class="tabbar-item" :class="{'tabbar-item-active': current === index}" @click="switchTab(item.pagePath)"><!-- 使用 Vant UI 的图标组件 --><van-icon :name="current === index ? item.selectedIcon : item.icon" class="tabbar-icon" :class="{'tabbar-icon-active': current === index}" /><text>{{ item.text }}</text></view></view>
</template><script>
// 定义路由映射关系,用于快速查找当前页面对应的索引
const TAB_ROUTES = {'/pages/index/index': 0,'/pages/detail/detail': 1,'/pages/course/course': 2, '/pages/profile/profile': 3
};export default {data() {return {current: 0, // 当前选中的 tab 索引tabList: [{pagePath: '/pages/index/index',text: '首页',icon: 'home-o',selectedIcon: 'home-o'},{pagePath: '/pages/detail/detail',text: '详情',icon: 'records',selectedIcon: 'records'},{pagePath: '/pages/course/course', text: '课程',icon: 'clock-o',selectedIcon: 'clock-o'},{pagePath: '/pages/profile/profile',text: '我的',icon: 'contact',selectedIcon: 'contact'}]}},methods: {// 切换 tab 的方法switchTab(url) {uni.switchTab({ url });}},watch: {// 监听路由变化,更新当前选中的 tab'$route.path': {immediate: true,handler(path) {this.current = TAB_ROUTES[path] || 0;}}}
}
</script><style>
/* Tabbar 容器样式 */
.custom-tabbar {position: fixed;bottom: 0;left: 0;right: 0;height: 110rpx;display: flex;justify-content: space-around;align-items: center;background-color: #fff;border-top: 1rpx solid #e2e8f0;box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);z-index: 9999;padding-bottom: env(safe-area-inset-bottom); /* 适配全面屏 */
}/* Tabbar 项基础样式 */
.tabbar-item {display: flex;flex-direction: column;align-items: center;justify-content: center;font-size: 24rpx;color: #64748b;padding: 10rpx 0;transition: all 0.2s ease;position: relative;
}/* 激活状态样式 */
.tabbar-item-active {color: #3b82f6;font-weight: 600;
}/* 点击效果 */
.tabbar-item:active {transform: scale(0.95);
}/* 图标样式 */
:deep(.tabbar-icon) {font-size: 48rpx !important;margin-bottom: 4rpx;
}/* 激活状态图标样式 */
:deep(.tabbar-icon-active) {color: #3b82f6 !important;
}/* 文字样式 */
.tabbar-item text {margin-top: 6rpx;font-weight: 500;
}/* 底部指示条 */
.tabbar-item-active:before {content: '';position: absolute;bottom: -10rpx;left: 50%;transform: translateX(-50%);width: 16rpx;height: 3px;background: #3b82f6;border-radius: 3px;
}
</style>
2.2 配置 pages.json
在 pages.json
中需要禁用原生 Tabbar,并配置页面路由:
{"tabBar": {"custom": true, // 启用自定义 Tabbar"list": [{"pagePath": "pages/index/index","text": "首页"},{"pagePath": "pages/detail/detail","text": "详情"},{"pagePath": "pages/course/course", "text": "课程"},{"pagePath": "pages/profile/profile","text": "我的"}]}
}
2.3 在 App.vue 中引入组件
在 App.vue
中引入并注册自定义 Tabbar 组件:
<template><view><custom-tabbar /></view>
</template><script>
import CustomTabbar from '@/components/CustomTabbar.vue'export default {components: {CustomTabbar}
}
</script>
3. 实现过程中的关键点
3.1 路由映射
使用 TAB_ROUTES
对象来映射路由路径和对应的索引值,这样可以方便地管理当前选中的 tab:
const TAB_ROUTES = {'/pages/index/index': 0,'/pages/detail/detail': 1,'/pages/course/course': 2, '/pages/profile/profile': 3
};
3.2 样式设计
- 使用
position: fixed
确保 Tabbar 固定在底部 - 添加
env(safe-area-inset-bottom)
适配全面屏手机 - 使用
box-shadow
添加阴影效果 - 实现点击缩放动画效果
- 添加底部指示条
3.3 图标处理
使用 van-icon
组件(来自 Vant UI)来显示图标,通过 :class
动态切换选中状态。
4. 常见问题及解决方案
4.1 页面跳转问题
问题:使用 uni.switchTab
跳转时可能出现页面不更新的情况。
解决方案:
- 确保在
pages.json
中正确配置了 tabBar - 使用
uni.switchTab
而不是uni.navigateTo
- 在
watch
中监听路由变化,及时更新选中状态
4.2 样式适配问题
问题:在不同机型上可能出现底部遮挡或样式错乱。
解决方案:
- 使用
env(safe-area-inset-bottom)
适配全面屏 - 设置合适的
z-index
确保层级正确 - 使用
rpx
单位确保在不同设备上显示一致
4.3 性能优化
问题:频繁切换可能导致性能问题。
解决方案:
- 使用
v-for
时添加:key
- 合理使用
watch
监听路由变化 - 避免在 Tabbar 中加载过多资源
5. 扩展功能
5.1 添加徽标
可以在 Tabbar 项上添加徽标,显示未读消息数量等:
<view class="tabbar-item"><van-icon :name="icon" /><text>{{ text }}</text><view v-if="badge" class="badge">{{ badge }}</view>
</view>
5.2 添加动画效果
可以添加更丰富的动画效果,如:
.tabbar-item {transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}.tabbar-item:hover {transform: translateY(-5rpx);
}
6. 总结
通过以上步骤,我们实现了一个功能完整、样式美观的自定义 Tabbar。这个实现方案具有以下特点:
- 支持路由跳转
- 适配不同机型
- 提供良好的视觉反馈
- 性能优化
- 易于扩展
作者:xuan
个人博客:https://blog.ybyq.wang
欢迎访问我的博客,获取更多技术文章和教程。
相关文章:

Uniapp 自定义 Tabbar 实现教程
Uniapp 自定义 Tabbar 实现教程 1. 简介2. 实现步骤2.1 创建自定义 Tabbar 组件2.2 配置 pages.json2.3 在 App.vue 中引入组件 3. 实现过程中的关键点3.1 路由映射3.2 样式设计3.3 图标处理 4. 常见问题及解决方案4.1 页面跳转问题4.2 样式适配问题4.3 性能优化 5. 扩展功能5.…...

记录一次使用面向对象的C语言封装步进电机驱动
简介 (2025/4/21) 本库对目前仅针对TB6600驱动下的42步进电机的基础功能进行了一定的封装, 也是我初次尝试以面向对象的思想去编写嵌入式代码, 和直流电机的驱动步骤相似在调用stepmotor_attach()函数和stepmotor_init()函数之后仅通过结构体数组stepm然后指定枚举变量中的id即…...

Spark-streaming核心编程
1.导入依赖: <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming-kafka-0-10_2.12</artifactId> <version>3.0.0</version> </dependency> 2.编写代码: 创建Sp…...
Exposure Adjusted Incidence Rate (EAIR) 暴露调整发病率:精准量化疾病风险
1. 核心概念 1.1 传统发病率的局限性 1.1.1 公式与定义 传统发病率公式为新发病例数除以总人口数乘以观察时间。例如在某社区观察1年,有10例新发病例,总人口1000人,发病率即为10/10001=0.01。 此公式假设所有个体暴露时间和风险相同,但实际中个体差异大,如部分人暴露时间…...

vue3+TS+echarts 折线图
需要实现的效果如下 <script setup lang"ts" name"RepsSingleLineChart">import * as echarts from echartsimport { getInitecharts } from /utils/echartimport type { EChartsOption } from echarts// 定义 props 类型interface Props {id: strin…...
MYSQL中为什么不建议delete数据
在 MySQL 中不建议频繁使用 delete 删除数据的原因主要在于性能、数据安全等方面的问题,以下是具体介绍: 性能问题 磁盘空间与碎片:delete 操作只是将数据标记为 “已删除”,并不会立即释放磁盘空间,频繁执行会导致大量…...
Linux多线程技术
什么是线程 在一个程序里的多执行路线就是线程。线程是进程中的最小执行单元,可理解为 “进程内的一条执行流水线”。 进程和线程的区别 进程是资源分配的基本单位,线程是CPU调度的基本单位。 fork创建出一个新的进程,会创建出一个新的拷贝&…...
12个HPC教程汇总!从入门到实战,覆盖分子模拟/材料计算/生物信息分析等多个领域
在科学研究、工程仿真、人工智能和大数据分析等领域,高性能计算 (High Performance Computing, HPC) 正扮演着越来越重要的角色。它通过并行处理、大规模计算资源的整合,极大提升了计算效率,使原本耗时数日的任务能够在数小时内完成。 随着计…...
[OpenGL] Lambertian材质漫反射BRDF方程的解释与推导
一、简介 本文简单的介绍了 Physical Based Rendering, PBR 中的 Lambertian 材质漫反射BRDF公式 f r l a m b e r t i a n c d i f f π fr_{lambertian}\frac{c_{diff}}{\pi} frlambertianπcdiff的推导。 二、漫反射项 根据 渲染方程: L o ( v ) ∫ …...

小火电视桌面TV版下载-小火桌面纯净版下载-官方历史版本安装包
别再费心地寻找小火桌面的官方历史版本安装包啦,试试乐看家桌面吧,它作为纯净版本的第三方桌面,具有诸多优点。 界面简洁纯净:乐看家桌面设计简洁流畅,页面简洁、纯净无广告,为用户打造了一个干净的电视操…...
VSFTPD+虚拟用户+SSL/TLS部署安装全过程(踩坑全通)
Author : Spinach | GHB Link : http://blog.csdn.net/bocai8058文章目录 前言准备配置虚拟用户1.创建虚拟用户列表文件2.生成数据库文件3.设置虚拟用户独立访问权限 配置PAM认证1.创建PAM配置文件2.测试PAM认证 创建虚拟用户映射的系统用户生成SSL/TLS证书配置VSFTPD服务1…...
07 Python 字符串全解析
文章目录 一. 字符串的定义二. 字符串的基本用法1. 访问字符串中的字符2. 字符串切片3. 字符串拼接4. 字符串重复5.字符串比较6.字符串成员运算 三. 字符串的常用方法1. len() 函数2. upper() 和 lower() 方法3. strip() 方法4. replace() 方法5. split() 方法 四. 字符串的进阶…...

androidstudio安装配置
B站配置视频AndroidStudio安装配置教程(最新版本教程)3分钟搞定 快速安装使用_哔哩哔哩_bilibili 1、环境变量 D:\AndroidSdk ANDROID_HOME ANDROID_SDK_HOME 2、新建 3、配置 distributionUrlhttps://mirrors.cloud.tencent.com/gradle/gradle-8.11.1-…...
全面解析 MCP(Model Context Protocol):AI 大模型的“万能连接器”
一、MCP 的定义与技术定位 **MCP(Model Context Protocol,模型上下文协议)**是由 Anthropic 公司于 2024 年 11 月推出的开源协议,旨在为 AI 大模型与外部数据源、工具之间建立标准化连接通道。它被业界称为 “AI 的 USB-C 接口”,通过统一的通信协议和数据结构,解决大模…...

《AI大模型趣味实战》基于RAG向量数据库的知识库AI问答助手设计与实现
基于RAG向量数据库的知识库AI问答助手设计与实现 引言 随着大语言模型(LLM)技术的快速发展,构建本地知识库AI问答助手已成为许多企业级应用的需求。本研究报告将详细介绍如何基于FLASK开发一个使用本地OLLAMA大模型底座的知识库AI问答助手&…...
Lua 第8部分 补充知识
8.1 局部变量和代码块 Lua 语言中的变量在默认情况下是全局变量 ,所有的局部变量在使用前必须声明 。 与全局变量不同,局部变量的生效范围仅限于声明它的代码块。一个代码块( block )是一个控制结构的主体,或是一个函…...
正则表达式三剑客之——awk命令
目录 一.什么是awk 二.awk的语法格式 1.选项 2. 模式(Pattern) 3. 操作(Action) 4. 输入文件(file) 5.总结 三.awk的工作原理 1. 逐行扫描输入 2. 匹配模式 1.正则表达式: 2.逻辑…...

BeeWorks Meet:私有化部署视频会议的高效选择
在数字化时代,视频会议已成为企业沟通协作的重要工具。然而,对于金融、政务、医疗等对数据安全和隐私保护要求极高的行业来说,传统的公有云视频会议解决方案往往难以满足其严格的安全标准。此时,BeeWorks Meet 私有化部署视频会议…...
[Mybatis-plus]
简介 MyBatis-Plus (简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变。Mybatis-plus官网地址 注意,在引入了mybatis-plus之后,不要再额外引入mybatis和mybatis-spring,避免因为版本…...

IPv6 技术细节 | 源 IP 地址选择 / Anycast / 地址自动配置 / 地址聚类分配
注:本文为 “IPv6 技术细节” 相关文章合集。 部分文章中提到的其他文章,一并引入。 略作重排,未整理去重。 如有内容异常,请看原文。 闲谈 IPv6 - 典型特征的一些技术细节 iteye_21199 于 2012-11-10 20:54:00 发布 0. 巨大的…...
【高频考点精讲】ES6 String的新增方法,处理字符串更方便了
ES6 String的新增方法:处理字符串从未如此优雅 【初级】前端开发工程师面试100题(一) 【初级】前端开发工程师面试100题(二) 【初级】前端开发工程师的面试100题(速记版) 作为天天和字符串打交道的码农,谁还没被indexOf和substring折磨过?ES6给String对象新增的几个方…...

【工具】使用 MCP Inspector 调试服务的完全指南
Model Context Protocol (MCP) Inspector 是一个交互式开发工具,专为测试和调试 MCP 服务器而设计。本文将详细介绍如何使用 Inspector 工具有效地调试和测试 MCP 服务。 1. MCP Inspector 简介 MCP Inspector 提供了直观的界面,让开发者能够ÿ…...

【音视频】AVIO输入模式
内存IO模式 AVIOContext *avio_alloc_context( unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t (*seek)(…...
AI与思维模型【76】——SWOT思维模型
一、定义 SWOT思维模型是一种用于分析事物内部和外部因素的战略规划工具。其中,S代表优势(Strengths),是指事物自身所具备的独特能力、资源或特点,这些因素有助于其在竞争中取得优势;W代表劣势(…...
大模型提示词如何编写
一、提示词的核心三要素 明确目标(What) 告诉 AI「你要它做什么」,越具体越好。 ❌ 模糊:写一篇文章 ✅ 清晰:写一篇 800 字的高考作文,主题 “坚持与创新”,结构分引言、三个论点(…...
python如何取消word中的缩进
在python-docx中,取消缩进可以通过将相应的缩进属性设置为None或0来实现。以下是取消不同类型缩进的方法: 取消左缩进 from docx import Documentdoc Document(existing_document.docx)for paragraph in doc.paragraphs:# 取消左缩进paragraph.paragr…...
DDL小练习
1.创建一张t_user表 要求属性有id(INT),name(VARCHAR),sex(VARCHAR),birthday(DATE) 其中id和name不能为空,添加数据并测试。 创建数据库 create database spt2503; 创建数据库中的t_user表 create table t_user (id int not null, name varchar(20) not…...

Uniapp:scroll-view(区域滑动视图)
目录 一、基本概述二、属性说明三、基本使用3.1 纵向滚动3.2 横向滚动一、基本概述 scroll-view,可滚动视图区域。用于区域滚动。 二、属性说明 属性名类型默认值说明平台差异说明scroll-xBooleanfalse允许横向滚动scroll-yBooleanfalse允许纵向滚动三、基本使用 3.1 纵向滚…...
【前端】【面试】在前端开发中,如何实现图片的渐进式加载,以及这样做的好处是什么?
题目:在前端开发中,如何实现图片的渐进式加载,以及这样做的好处是什么? 在浏览器端实现图片的“渐进式加载”(Progressive Image Loading)常用的三种方式 方法思路典型实现要点适用场景优缺点简述1. 使…...

单精度浮点运算/定点运算下 MATLAB (VS) VIVADO
VIVADO中单精度浮点数IP核计算结果与MATLAB单精度浮点数计算结果的对比 MATLAB定点运算仿真,对比VIVADO计算的结果 目录 前言 一、VIVADO与MATLAB单精度浮点数运算结果对比 二、MATLAB定点运算仿真 总结 前言 本文介绍了怎么在MATLAB中使用单精度浮点数进行运算…...