UNI-APP 自定义微信小程序底部导航栏

本文只针对于微信小程序的自定义底部导航栏;
PS:可能在进入小程序后,首次点击tabBar会出现闪烁的情况;不能接受的就还是乖乖的用回默认吧!

需求

在开发记账APP时,感觉微信小程序默认的tabBar功能很简单,而且不能进行美化,作为强迫症的我,不能忍,直接搂它;
我需要达到的效果如下:

  • 中间的按钮凸起;
  • 中间的按钮点击时需要跳转二级页面;

方案

当然,我们以UNI-APP官方的案例为主,先看一下官方怎么做的:UNI-APP 自定义 tabBar
官方文档也是描述了一下,具体实现也还是需要使用wxml、wxss进行实现,并且需要将自定义tabBar放在项目根目录下的custom-tab-bar文件夹下;最终方案也是跳到了微信社区:微信小程序 自定义 tabBar

实现

1、修改配置page.json文件

添加custom字段,并赋值true,表示这里我们使用的是自定义的tabBar;
此时,我们这里的配置数据就不生效了;

2、添加自定义tabBar

a、创建文件夹

文件包含自定义tabBar:index.js、index.json、index.wxml、index.wxss

针对我上述图中的效果,代码如下:

index.js
Component({
  data: {
    selected: 0,
    color: "#D1D1D1",
    selectedColor: "#A6B1E1",
    list: [{
      "pagePath": "/pages/index/index",
      "text": "账目"
    },
    {
      "pagePath": "/pages/profile/index",
      "text": "我的"
    }]
  },
  attached() {
  },
  methods: {
    switchTab(e) {
      const data = e.currentTarget.dataset
      const url = data.path
      wx.switchTab({ url })
      this.setData({
        selected: data.index,
      })
    },
    // 此处需要针对中间的tabBar跳转到二级页面,而不是使用switchTab
    toadd() {
      wx.navigateTo({ url: '/pages/bill/edit' })
    }
  }
})
index.json
{
  "component": true
}
index.wxml
<!--miniprogram/custom-tab-bar/index.wxml-->
<view class="tab-bar">
  <view wx:for="{{list}}" wx:key="index" class="tab-bar-item {{item.bulge?'bulge':''}}" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab">
    <view  wx:if="item.bulge" class="tab-bar-bulge tab-bar-view"></view>
    <image style="display: {{item.bulge? 'block' : 'none'}};" class="image" src="{{selected === index ? item.selectedIconPath : item.iconPath}}"></image>
    <view  wx:if="{{item.text}}" style="color: {{selected === index ? selectedColor : color}}" class="tab-bar-view">{{item.text}}</view>
  </view>
  <view class="bulge"  bindtap="toadd">
    <view class="background">
      <image class="image" src="/static/assets/tabbar/plus.png"></image>
    </view>
  </view>
</view>
index.wxss
.tab-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 48px;
  display: flex;
  line-height: 1.2;
  padding-bottom: env(safe-area-inset-bottom);
  background: white;

}

.tab-bar-item {
  flex: 1;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}
.tab-bar-item .image {
  width: 27px;
  height: 27px;
}

.bulge {
  position: absolute;
  left: 50%;
  right: 50%;
  transform: translate(-50%);
  top: -12px;
  height: 80px;
  width: 60px;
  display: flex;
  justify-content: center;
}

.bulge .background{
  background: #A6B1E1;
  width: 45px;
  height: 45px;
  border-radius: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.bulge .background .image{
  width: 20px;
  height: 20px;
}

.tab-bar-item .tab-bar-view {
  font-size: 13px;
  font-weight: bold;
}

3、修改tabBar指向页面

实际开发中,如果不进行此项处理则会导致点击tabBar时出现奇怪的问题:点击另外一个bar时,上一个bar才会处于被选中状态;

解决该问题就要在每个tabBar指向页面的onShow添加如下代码:
PS:网上很多教程都是使用this.$mp.getTabBarthis.$root.$mp.getTabBar去实现(uni-app v2.0.0之前应该没事),但会在热重载tab page时都会报错:Error in onShow hook: "TypeError: Cannot read property 'getTabBar' of undefined",如下图:

经过一番issue折腾后,最终使用如下实现:

onShow() {
    // 网上很多教程都是使用this.$mp.getTabBar 或 this.$root.$mp.getTabBar去实现
    // 但目前的uni-app(2.0.1)版本下会出现undefined的情况,官方的解决方案是使用如下方式
    if (typeof this.$scope.getTabBar === 'function' &&
        this.$scope.getTabBar()) {
        this.$scope.getTabBar().setData({
            // 当前页面对应的tab index
            selected: 0,
        })
    }
}

但是,我们需要优雅点,使用mixins进行混入,达到一个function随处使用,且本文使用的时局部混入,需要在使用到的页面进行混入,代码如下:

构建mixins

根目录下创建mixins文件夹,并创建tabbar.js

export const mixin = {
    methods: {
        setTabBarIndex(index) {
            if (typeof this.$scope.getTabBar === 'function' &&
                this.$scope.getTabBar()) {
                this.$scope.getTabBar().setData({
                    selected: index,
                })
            }
        }
    }
}
在需要混入的页面进行配置
// 引入混入js
import { mixin } from "@/mixins/tabbar.js";

export default {
  mixins: [mixin], //混入js文件
  onShow() {
    this.setTabBarIndex(0);
  },
}

需要注意

  • 在UNI-APP编译后,生成了dist文件夹后再进行此项更改,且直接热更新使用的话会出现两个tabBar且重叠的情况,此时需要删除dist,并重新生成;
posted @ 2022-05-06 10:14  Memoyu  阅读(3003)  评论(0编辑  收藏  举报