专注小程序 / APP 开发,用代码改变生活

获取方案
全国分站 主站首页 北京分站 石家庄分站 唐山分站 保定分站 廊坊分站 沧州分站 郑州分站

微信小程序自定义tabbar实战

小程序开发 2026-10-21 1 阅读 0 点赞 原创

做微信小程序的朋友大多遇到过这种尴尬:产品经理拿着设计稿说,这个 tabbar 要中间凸起一个按钮,图标要能带角标,选中态要有个小动画。而小程序原生 tabBar 只支持静态配置,改个图标都得重新编译,更别说凸起和动画了。这时候就得上自定义 tabbar。

自定义 tabbar 的核心思路其实不复杂:把原生 tabbar 隐藏掉,自己写一个 fixed 定位的组件,用 wx.switchTab 做页面切换。但坑也不少,比如切换时的闪烁、选中态不同步、页面栈判断错误等。下面把我踩过的坑和最终方案整理出来。

一、开启自定义 tabbar

在 app.json 里给 tabBar 加一个 custom: true,同时保留 list 配置(list 里的 pagePath 必须和真实页面一致,否则 switchTab 会失败):

{
  "tabBar": {
    "custom": true,
    "list": [
      { "pagePath": "pages/index/index", "text": "首页" },
      { "pagePath": "pages/category/category", "text": "分类" },
      { "pagePath": "pages/cart/cart", "text": "购物车" },
      { "pagePath": "pages/mine/mine", "text": "我的" }
    ]
  }
}

然后在项目根目录新建 custom-tab-bar 文件夹,注意这个名字是固定的,不能改。里面放 index.js / index.json / index.wxml / index.wxss 四个文件,index.json 里要声明 "component": true。

二、组件逻辑实现

组件里最关键的是 selected 状态和切换方法。这里有个细节:每个 tab 页面都要在 onShow 里调用 this.getTabBar().setData({ selected: 0 }) 来同步选中态,否则从其他页面返回时高亮会错乱。

// custom-tab-bar/index.js
Component({
  data: {
    selected: 0,
    list: [
      { pagePath: '/pages/index/index', text: '首页', icon: 'home' },
      { pagePath: '/pages/category/category', text: '分类', icon: 'grid' },
      { pagePath: '/pages/cart/cart', text: '购物车', icon: 'cart' },
      { pagePath: '/pages/mine/mine', text: '我的', icon: 'user' }
    ]
  },
  methods: {
    switchTab(e) {
      const { index, path } = e.currentTarget.dataset;
      if (this.data.selected === index) return;
      wx.switchTab({
        url: path,
        success: () => {
          this.setData({ selected: index });
        }
      });
    }
  }
});

对应的 wxml 用 flex 布局,中间凸起按钮可以单独用绝对定位抬高:

<view class="tab-bar">
  <view
    wx:for="{{list}}"
    wx:key="pagePath"
    class="tab-item {{selected === index ? 'active' : ''}}"
    data-index="{{index}}"
    data-path="{{item.pagePath}}"
    bindtap="switchTab"
  >
    <view class="icon icon-{{item.icon}}"></view>
    <text>{{item.text}}</text>
  </view>
</view>

三、页面同步选中态

每个 tab 页面都要加这段,建议封装成 mixin 或者直接复制,四个页面也就几行:

onShow() {
  if (typeof this.getTabBar === 'function' && this.getTabBar()) {
    this.getTabBar().setData({ selected: 0 }); // 按页面改索引
  }
}

四、几个容易踩的坑

  • 闪烁问题:自定义 tabbar 首次加载会有短暂空白,可以在 app.wxss 里给 tabbar 预留高度,或者用 wx.hideTabBar() 配合,但更推荐直接在组件里加骨架样式。
  • 页面栈判断:不要用 getCurrentPages() 去反推索引,容易在多级跳转后出错,老老实实每个页面 setData 最稳。
  • 角标和红点:购物车数量这类动态数据,建议放在全局 store(如 mobx-miniprogram 或简单的 globalData)里,tabbar 组件监听变化,避免每个页面重复请求。
  • 安全区适配:iPhone 底部有 home indicator,tabbar 高度要用 env(safe-area-inset-bottom) 补 padding,不然会被遮挡。

五、小结

自定义 tabbar 本身代码量不大,难点在于状态同步和细节适配。我的建议是:如果只是改个图标颜色,原生配置够用就别折腾;一旦涉及凸起按钮、动态角标、切换动画,再上自定义方案。另外记得在真机上多测几种机型,尤其是刘海屏和折叠屏,安全区适配做不好,体验会打折扣。

这套方案我在几个电商类小程序里都跑过,稳定性和性能都没问题。如果你也在做类似需求,可以直接拿去改,省下的时间够喝杯咖啡了。

微信小程序自定义头部实战技巧微信小程序接入企业微信客服实战

评论 (0)

还没有评论,快来抢沙发吧~

好想法,值得被认真交付

从小程序、APP 到全栈网站,一站式把想法变成可落地的产品

微信咨询

微信扫码,直接沟通需求