小程序动态tabbar

456 阅读2分钟

根据登录用户的角色,展示不同的TabBar,比如普通用户显示3个tab,管理员显示4个tab,本文是基于原生小程序实现的,本文使用Math.randomdelay模拟登录者角色(后面会讲)

代码仓库 custom-tab-bar

参考文档

效果如下:

普通用户:

tab.png

管理员:

tab2.png

1.新建小程序目录如下

    |-- app.js
    |-- app.json
    |-- app.wxss
    |-- assets
    |   |-- index.png
    |   |-- index_selected.png
    |   |-- manage.png
    |   |-- manage_selected.png
    |   |-- mine.png
    |   |-- mine_selected.png
    |   |-- order.png
    |   |-- order_selected.png
    |-- custom-tab-bar
    |   |-- index.js
    |   |-- index.json
    |   |-- index.wxml
    |   |-- index.wxss
    |   |-- tabs.js
    |-- pages
        |-- index
        |   |-- index.js
        |   |-- index.json
        |   |-- index.wxml
        |   |-- index.wxss
        |-- manage
        |   |-- index.js
        |   |-- index.json
        |   |-- index.wxml
        |   |-- index.wxss
        |-- mine
        |   |-- index.js
        |   |-- index.json
        |   |-- index.wxml
        |   |-- index.wxss
        |-- order
            |-- index.js
            |-- index.json
            |-- index.wxml
            |-- index.wxss

2.custom-tab-bar

首页下app.json设置

  "tabBar": {
    "color": "#c6c6c6",
    "borderStyle": "white",
    "selectedColor": "#3e5e64",
    "custom": true,
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页",
        "iconPath": "/assets/index.png",
        "selectedIconPath": "/assets/index_selected.png"
      },
      {
        "pagePath": "pages/order/index",
        "text": "订单",
        "iconPath": "/assets/order.png",
        "selectedIconPath": "/assets/order_selected.png"
      },
      {
        "pagePath": "pages/manage/index",
        "text": "管理",
        "iconPath": "/assets/manage.png",
        "selectedIconPath": "/assets/manage_selected.png"
      },
      {
        "pagePath": "pages/mine/index",
        "text": "我的",
        "iconPath": "/assets/mine.png",
        "selectedIconPath": "/assets/mine_selected.png"
      }
    ]
  },

新建名为custom-tab-bar的自定义组件,写页面结构及样式和逻辑,大概实现就是在生命周期函数中根据不同角色加载不同的tab数据即可(这个逻辑在首页也需处理,后面会介绍)

index.wxml

<view class="tab-bar">
  <view class="tab-bar-border"></view>
  <view 
      wx:for="{{list}}" 
      wx:key="index" 
      class="tab-bar-item" 
      data-path="{{item.pagePath}}" 
      data-index="{{index}}" 
      bindtap="switchTab">
    <image 
        class="image" 
        src="{{selected === index ? item.selectedIconPath : item.iconPath}}"
        mode="aspectFit">
    </image>
    <view 
        class="text" 
        style="color: {{selected === index ? selectedColor : color}}">
        {{item.text}}
    </view>
  </view>
</view>

index.wxss

.tab-bar {
  height: 48px;
  background: white;
  display: flex;
  padding-bottom: env(safe-area-inset-bottom);
  border-top: 1px solid #ccc;
}

.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;
}

.tab-bar-item .text {
  font-size: 10px;
}

index.json

"component": true,

index.js

import tabs from './tabs';
const app = getApp();

Component({
  /**
   * 组件的属性列表
   */
  properties: {},

  /**
   * 组件的初始数据
   */
  data: {
    selected: 0, // 选中哪个tab
    color: '#c6c6c6',
    selectedColor: '#3e5e64',
    list: [],  // tabs 展示3个或4个
  },

  /**
   * 生命周期方法
   */
  async attached() {
    // 管理员
    if (wx.getStorageSync('is_admin') == '1') {
      this.setData({
        list: tabs.tab2,
      });
    }
    // 普通用户
    if (wx.getStorageSync('is_admin') == '0') {
      this.setData({
        list: tabs.tab1,
      });
    }
  },

  /**
   * 组件的方法列表
   */
  methods: {
    switchTab(ev) {
      const path = ev.currentTarget.dataset.path;
      // this.isAdmin(); 
      // => 真实项目中防止用户角色做了修改,需要跳转的时间验证角色
      wx.switchTab({
        url: path,
      });
    },
    // 判断当前用户是否是admin
    async isAdmin() {
      const res = {
        code: 0,
        data: { is_admin: '1' },
      };
      if (res.code === 0) {
        if (wx.getStorageSync('is_admin') != res.data.is_admin) {
          wx.setStorageSync('is_admin', res.data.is_admin);
          wx.reLaunch({
            url: '/pages/index/index',
          });
        }
      }
    },
  },
});

3.tab页面

自定义组件新增 getTabBar 接口,可获取当前页面下的自定义 tabBar 组件实例

pages/index/index

import tabs from '../../custom-tab-bar/tabs';

Page({
  data: {},
  async onLoad(options) {
    // 模拟接口获取用户角色
    const delay = async ms => {
      return new Promise(resolve => {
        setTimeout(() => {
          if (wx.getStorageSync('is_admin') === '') {
            const random = Math.random() > 0.5 ? '1' : '0'; 
            // '1'管理员 '0'普通用户
            wx.setStorageSync('is_admin', random);
          }
          resolve(ms);
        }, ms);
      });
    };
    await delay(200);
    if (wx.getStorageSync('is_admin') === '1') {
      this.getTabBar().setData({
        list: tabs.tab2,
      });
    }
    if (wx.getStorageSync('is_admin') === '0') {
      this.getTabBar().setData({
        list: tabs.tab1,
      });
    }
  },
  onShow() {
    if (typeof this.getTabBar === 'function' && this.getTabBar()) {
      this.getTabBar().setData({
        selected: 0,
      });
    }
  },
});

其他tab页

pages/order/index

  onShow() {
    if (typeof this.getTabBar === 'function' && this.getTabBar()) {
      this.getTabBar().setData({
        selected: 1, 
      });
    }
  },

pages/manage/index

  onShow() {
    if (typeof this.getTabBar === 'function' && this.getTabBar()) {
      this.getTabBar().setData({
        selected: 2, 
      });
    }
  },

pages/mine/index

  onShow() {
    if (typeof this.getTabBar === 'function' && this.getTabBar()) {
      this.getTabBar().setData({
        selected: wx.getStorageSync('is_admin') == 1 ? 3 : 2,
      });
    }
  },

4.总结

custom-tab-bar适用于,对小程序tab有比较特殊的要求,比如样式自定义,或者根据登录角色显示不同的导航