← 返回题目列表

小程序自定义 tabBar 如何实现?和原生 tabBar 有什么区别?

高频 中等 第 14 / 32 题 更新于 2026/07/29
小程序tabBar自定义组件导航

简化版

原生 tabBar 通过 app.json 配置,简单稳定但样式和交互受限;自定义 tabBar 通过开启 custom 并实现自定义组件,可以做更复杂的 UI、红点、凸起按钮和业务状态,但需要自己处理选中态、页面同步、性能和兼容问题。

详细版

原生 tabBar:

{
  "tabBar": {
    "list": [
      { "pagePath": "pages/home/index", "text": "首页" },
      { "pagePath": "pages/mine/index", "text": "我的" }
    ]
  }
}

自定义 tabBar 通常需要:

  1. app.jsontabBar 中开启 custom: true
  2. 创建 custom-tab-bar 组件。
  3. 在各 tab 页面同步 selected 状态。
  4. wx.switchTab 切换 tab 页面。
  5. 处理红点、徽标、权限、登录态和样式适配。

面试重点是:自定义 tabBar 灵活性更高,但维护成本也更高。

完整版教学

一、原生 tabBar 是配置驱动

小程序原生 tabBar 通过 app.json 配置。它的优点是简单、性能稳定、平台一致性好,适合大多数常规底部导航。

{
  "tabBar": {
    "color": "#666666",
    "selectedColor": "#07c160",
    "list": [
      { "pagePath": "pages/home/index", "text": "首页" },
      { "pagePath": "pages/order/index", "text": "订单" },
      { "pagePath": "pages/mine/index", "text": "我的" }
    ]
  }
}

它的限制也明显:布局结构、动画效果、特殊按钮形态、复杂状态展示都受平台配置约束。如果产品要中间凸起发布按钮、动态会员样式、复杂徽标,就可能需要自定义 tabBar。

面试回答要先表明态度:能用原生就优先原生,只有设计和业务状态确实超出原生能力时再自定义。

二、自定义 tabBar 的核心是 custom-tab-bar 组件

自定义 tabBar 通常先在配置里开启 custom: true,再在项目根目录下创建 custom-tab-bar 组件。平台会在 tab 页面底部渲染这个组件。

{
  "tabBar": {
    "custom": true,
    "list": [
      { "pagePath": "pages/home/index", "text": "首页" },
      { "pagePath": "pages/mine/index", "text": "我的" }
    ]
  }
}

组件内部维护 tab 列表、图标、文字、选中态,并在点击时调用 wx.switchTab

Component({
  data: {
    selected: 0,
    list: [
      { pagePath: '/pages/home/index', text: '首页' },
      { pagePath: '/pages/mine/index', text: '我的' }
    ]
  },
  methods: {
    switchTab(e) {
      const { path } = e.currentTarget.dataset
      wx.switchTab({ url: path })
    }
  }
})

三、选中态同步是最常见坑

自定义 tabBar 不会自动知道当前页面应该选中哪个 tab,需要页面在 onShow 中主动同步,或通过统一映射计算当前路由。

Page({
  onShow() {
    const tabBar = this.getTabBar && this.getTabBar()
    if (tabBar) {
      tabBar.setData({ selected: 1 })
    }
  }
})

假设有 4 个 tab 页面,如果其中 1 个页面忘记设置 selected,用户从其他页面切回来时,就可能出现“页面是订单,底部却高亮首页”的错位。

进入 tab 页面
  -> onShow
  -> getTabBar()
  -> setData({ selected })
  -> 底部选中态更新

工程里通常抽一个 setTabBarSelected(index) 工具函数,避免每个页面写法不同。

四、switchTab、navigateTo 和页面栈区别

tab 页面必须使用 wx.switchTab 切换。navigateTo 不能跳转到 tabBar 页面,switchTab 会关闭其他非 tab 页面并切换到 tab 页面。

API能否跳 tab 页面页面栈影响场景
wx.switchTab切换 tab,关闭非 tab 页面底部导航
wx.navigateTo不能跳 tab入栈新页面普通详情页
wx.redirectTo不能跳 tab替换当前页登录后替换
wx.reLaunch清空并打开重置应用状态

如果自定义 tabBar 点击时误用 navigateTo,会直接失败或表现异常。面试追问“为什么 tab 页面跳转特殊”,就是考页面栈模型。

五、红点、徽标和登录态要控制数据来源

自定义 tabBar 常用于展示购物车数量、消息红点、会员状态。这里要注意数据来源和更新频率。

App 全局状态 / 请求接口
  -> tabBar 组件 setData
  -> badge / redDot 更新

假设消息数每 5 秒刷新一次,而 tabBar 每个页面都重新请求,5 个 tab 页面切换一轮就可能触发多次重复请求。更好的方式是集中管理状态,页面显示时按需刷新,或者由消息模块统一推送变化。

数字例子:一个用户 1 分钟切换 tab 20 次,如果每次都请求 3 个徽标接口,就是 60 次请求,完全没必要。可以合并成 1 个 badge 接口,并做短时间缓存。

记忆钩子:自定义 tabBar 的难点不是画出来,而是让选中态、徽标、权限和页面栈一直正确。

六、样式适配和性能要额外关注

自定义 tabBar 要自己处理安全区、不同机型高度、暗色模式、图标加载和点击反馈。原生 tabBar 帮你处理了很多平台细节,自定义后这些成本回到开发者身上。

.tabbar {
  padding-bottom: env(safe-area-inset-bottom);
}

如果图标使用远程图片,弱网下可能出现底部图标闪烁。更稳妥的做法是使用本地小图标、雪碧图或字体图标,并控制资源大小。

性能上,tabBar 是高频可见组件,不要在组件里做重计算、大量请求或频繁 setData。选中态变化只需要更新少量字段,不应重设整个列表大对象。

七、常见误区与追问

  • 误区:自定义 tabBar 一定比原生好。 自定义更灵活,但选中态、适配、性能和维护成本更高。
  • 误区:tab 页面可以用 navigateTo 跳转。 tab 页面应使用 wx.switchTab,页面栈规则不同。
  • 误区:自定义 tabBar 会自动同步选中态。 通常需要页面在 onShow 中主动设置 selected。
  • 追问:为什么红点状态容易乱? 数据来源分散、页面切换重复请求、登录态变化未同步都会导致错乱。
  • 追问:什么时候坚持用原生 tabBar? 样式简单、状态少、追求稳定和平台一致性时优先原生。
  • 追问:自定义 tabBar 要注意哪些适配? 安全区、机型高度、暗色模式、图标资源、点击反馈和基础库兼容。

八、加强记忆

tabBar 题按“原生稳,自定义活”记:原生配置简单可靠,自定义组件灵活但要自己管 selected、switchTab、badge、登录态、安全区和性能。能把页面栈规则和选中态同步讲清楚,就抓住了这题的关键。