Uniapp 自定义 Tabbar 实现教程

    • 1. 简介
    • 2. 实现步骤
      • 2.1 创建自定义 Tabbar 组件
      • 2.2 配置 pages.json
      • 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": "我的"}]}
}

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。这个实现方案具有以下特点:

  1. 支持路由跳转
  2. 适配不同机型
  3. 提供良好的视觉反馈
  4. 性能优化
  5. 易于扩展

作者:xuan
个人博客:https://blog.ybyq.wang
欢迎访问我的博客,获取更多技术文章和教程。

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

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

相关文章

JuiceFS存储

因语雀与csdn markdown 格式有区别&#xff0c;请查看原文&#xff1a; https://www.yuque.com/dycloud/pss8ys 一、JuiceFS 介绍 1.1 JuiceFS 是什么 JuiceFS 是一款面向云环境设计的高性能 POSIX 文件系统&#xff0c;核心能力是将对象存储转化为全功能文件系统。它采用独…

【HarmonyOS Next之旅】DevEco Studio使用指南(三十八) -> 构建HAR

目录 1 -> 前言 2 -> 使用约束 3 -> 创建模块 4 -> 构建HAR 4.1 -> 以debug模式构建HAR 4.2 -> 以release模式构建HAR 4.3 -> 构建字节码格式的HAR 4.4 -> 对HAR进行签名 1 -> 前言 构建模式&#xff1a;DevEco Studio默认提供debug和rele…

93、【OS】【Nuttx】【构建】cmake menuconfig 目标

【声明】本博客所有内容均为个人业余时间创作&#xff0c;所述技术案例均来自公开开源项目&#xff08;如Github&#xff0c;Apache基金会&#xff09;&#xff0c;不涉及任何企业机密或未公开技术&#xff0c;如有侵权请联系删除 背景 接之前 blog 【OS】【Nuttx】【构建】cm…

React 表单处理:移动端输入场景下的卡顿问题与防抖优化方案

文章目录每日一句正能量前言一、问题场景与表现二、技术攻坚过程三、优化效果与经验沉淀每日一句正能量 山再高&#xff0c;往上攀&#xff0c;总能登顶&#xff1b;路再长&#xff0c;走下去&#xff0c;终将到达。每日一励&#xff0c;勇往直前。 前言 在移动端 React 项目开…

数据安全防护所需要的关键要素

数据安全防护是一个覆盖数据全生命周期&#xff08;采集、存储、传输、处理、销毁&#xff09;、融合技术、管理、流程与人员的系统性工程。其核心目标是保障数据的​​保密性&#xff08;Confidentiality&#xff09;、完整性&#xff08;Integrity&#xff09;、可用性&#…

【JavaEE】(8) 网络原理 HTTP/HTTPS

一、什么是 HTTP 协议 上节说到&#xff0c;应用层的协议需要约定通信的内容和数据格式。我们可以自定义应用层协议&#xff0c;也可以基于现成的应用层协议进行开发。协议的种类很多&#xff0c;最常见的之一就是 HTTP&#xff0c;广泛用于网站和手机 App。准确来说&#xff0…

C语言的数组与字符串练习题4

C语言的数组与字符串练习题4 16. 数组元素去重 题目描述: 编写一个C程序,输入一组整数存储在数组中,去除数组中的重复元素,并输出去重后的数组。 解题思路: 遍历数组,对于每个元素,检查它之前是否已经存在相同的元素。如果不存在,则将其保留;否则,跳过。可以使用一…

Transformers简单介绍 - 来源于huggingface

Transformers介绍 - 来源于huggingface 文章目录Transformers介绍 - 来源于huggingfaceTransformers能做什么pipeline()函数零样本分类推理API完形填空命名实体识别问答摘要提取翻译transformers是如何工作的transformers的具体组成注意力层机制transformers原始结构architectu…

template<typename R = void> 意义

在 C 中&#xff0c;template<typename R void> 表示定义一个模板参数 R&#xff0c;其默认类型为 void。这意味着&#xff1a;如果用户没有显式指定 R&#xff0c;则 R 默认为 void。如果用户显式指定了 R&#xff08;如 template<typename R void> 后面跟着 &l…

国产3D大型装配设计新突破①:图纸打开设计双加速 | 中望3D 2026

本文为CAD芯智库整理&#xff0c;未经允许请勿复制、转载&#xff01;在中望3D 2026的新版中&#xff0c;不仅在设计效率上进行了重大优化&#xff0c;更是在装配方面实现了突破性的改进&#xff0c;让每一个项目都能快速、精确地从概念变为现实。 中望3D2026亮点速递装配篇将…

游戏开发状态机与行为树的优缺点

在游戏开发中&#xff0c;状态机&#xff08;Finite State Machine, FSM&#xff09; 和行为树&#xff08;Behavior Tree, BT&#xff09; 是两种常用的 AI 逻辑控制框架&#xff0c;分别适用于不同场景&#xff0c;其优缺点对比可从灵活性、维护成本、适用场景等多个维度分析…

Linux下ELF文件的介绍

目录 1.温故知新 2.ELF文件介绍 3.ELF文件组成 4.ELF文件形成到加载 5.连接过程 1.温故知新 上一篇博客&#xff0c;我们介绍了我们的动静态&#xff0c;知道了我们的库其实也是文件&#xff0c;如果我们想写一个库也是可以的&#xff0c;我们的把我们的库文件编译成.o文件…

人工智能领域、图欧科技、IMYAI智能助手2025年6月更新月报

2025年6月AI领域重要模型更新与平台优化汇总 摘要&#xff1a; 本文汇总了2025年6月期间AI领域发布的多项重要模型更新及平台功能优化信息&#xff0c;涵盖Google Gemini、阿里通义万相、字节豆包、百度文心一言、MiniMax海螺02、Google Veo3、快手可灵2.1、FLUX Kontext等模型…

从零开始学Express,理解服务器,路由于中间件

当我们初学前端时&#xff0c;常常只关注页面效果和交互&#xff0c;但随着项目复杂度提升&#xff0c;我们迟早会遇到“服务端”的问题&#xff1a;如何让一个页面的数据是从数据库来的&#xff1f;怎么让不同的用户看到不同的内容&#xff1f;这时候&#xff0c;我们就需要一…

Codeforces Round 987 (Div. 2)

ABC 略D预处理出每个位置的前缀最大和后缀最小。从后向前枚举&#xff0c;如果一个数无法后移&#xff0c;那么答案就是最大前缀&#xff0c;否则答案要不是前缀最大&#xff0c;要不就是这个数先移到前缀最大位置再移到能移到的最大的位置此处的答案。用线段树维护#include<…

Javascript/ES6+/Typescript重点内容篇——手撕(待总结)

前端核心知识点梳理与面试题详解 1. Promise 核心知识点 Promise 是异步编程的解决方案&#xff0c;用于处理异步操作三种状态&#xff1a;pending&#xff08;进行中&#xff09;、fulfilled&#xff08;已成功&#xff09;、rejected&#xff08;已失败&#xff09;状态一旦改…

[自动化Adapt] 父子事件| 冗余过滤 | SQLite | SQLAlchemy | 会话工厂 | Alembic

第五章&#xff1a;事件处理与融合 欢迎回到OpenAdapt探索之旅~ 在第四章&#xff1a;系统配置中&#xff0c;我们掌握了如何定制化系统参数。更早的第一章&#xff1a;录制引擎则展示了系统如何捕获海量原始操作数据。 假设我们需要训练机器人输入"hello"一词。原…

组合期权:跨式策略

文章目录0.简介1.买入跨式组合&#xff08;Long Straddle&#xff09;1.1 适用场景​1.2 合约选择1.3 损益分析1.4 案例示范2.卖出跨式组合&#xff08;Short Straddle&#xff09;2.1 适用场景​2.2 合约选择2.3 损益分析2.4 案例示范3.小结参考文献0.简介 跨式策略是一种交易…

Vue计算属性详解2

可写计算属性 计算属性默认是只读的,但在特殊场景下,我们可以创建"可写"的计算属性,通过同时提供getter和setter实现: <script setup>import { ref, computed } from vueconst firstName = ref(John)const lastName = ref(Doe)const fullName = computed(…

UniStorm 5.3.0 + Unity2022 + URP配置说明

一、前言 以前我用的是UniStorm3.0&#xff0c;主要用在内置管线里面&#xff0c;最近想在URP管线里面使用UniStorm天气系统&#xff0c;于是弄了UniStorm5.3.0的包&#xff0c;在Unity2022.3的URP模式下配置&#xff0c;直接导入package&#xff0c;两次宣告失败。最后看了官方…