微信小程序自定义tabBar

1.app.json中tabBar里设置 "custom":true

设置好后就可使用自定义tabBar。

注意:list中的页面必须保存,且必须和自定义的tabBar页面数据一致

"tabBar": {
    "custom": true,
    "list": [{
      "pagePath": "pages/home/home",
      "text": "首页",
      "iconPath": "/images/tabs/home.png",
      "selectedIconPath": "/images/tabs/home-active.png"
    },{
      "pagePath": "pages/message/message",
      "text": "消息",
      "iconPath": "/images/tabs/message.png",
      "selectedIconPath": "/images/tabs/message-active.png"
    },{
      "pagePath": "pages/contact/contact",
      "text": "联系我们",
      "iconPath": "/images/tabs/contact.png",
      "selectedIconPath": "/images/tabs/contact-active.png"
    }]
  },

2.创建tabBar代码文件

在根目录下创建custom-tab-bar文件夹,并创建名为index的component组件。

注意以下三点,否则自定义tabBar不会生效:

  • 必须是根目录下
  • 且文件夹必须名为custom-tab-bar
  • 文件夹下的component组件名必须为index

3.npm下载vant weapp包,并在app.json中引入以下组件

  "usingComponents": {
    "van-button": "@vant/weapp/button/index",
    "van-tabbar": "@vant/weapp/tabbar/index",
    "van-tabbar-item": "@vant/weapp/tabbar-item/index"
  }

 4.自定义tabBar文件 index.wxml文件中,使用<van-tabBar>生成tabBar结构

image 标签中,slot中icon代表非选中图标,icon-active代表选中图标

<van-tabbar active="{{ active }}" bind:change="onChange"
active-color="#07c160">
  <van-tabbar-item info="{{item.info>0?item.info:''}}" wx:for="{{list}}" wx:key="name">
    <image
      slot="icon"
      src="{{ item.icon.normal }}"
      mode="aspectFit"
      style="width: 30px; height: 18px;"
    />
    <image
      slot="icon-active"
      src="{{ item.icon.active }}"
      mode="aspectFit"
      style="width: 30px; height: 18px;"
    />
    {{item.name}}
  </van-tabbar-item>
</van-tabbar>

5.在index.ts中,创建tabBar页面数据

info表示徽标;pagePath表示tab对象页面路径;icon表示选中和非选中图标存放路径

data: {
    // active: 0,
    // list的pagePath: "/pages/home/home"必须再app.json中有对应数据
    list:[{
      info:3,
      name:"首页",
      pagePath: "/pages/home/home",
      icon: {
        normal: '/images/tabs/home.png',
        active: '/images/tabs/home-active.png',
      },
    },{
      name:"消息",
      pagePath: "/pages/message/message",
      icon: {
        normal: 'https://img.yzcdn.cn/vant/user-inactive.png',
        active: 'https://img.yzcdn.cn/vant/user-active.png',
      },
    },{
      name:"联系我们",
      pagePath: "/pages/contact/contact",
      icon: {
        normal: 'https://img.yzcdn.cn/vant/user-inactive.png',
        active: 'https://img.yzcdn.cn/vant/user-active.png',
      },
    }
  ],
  },

6.渲染徽标

通过info属性控制徽标显示,为 '' 时自动不显示,info="{{item.info>0?item.info:''}}"表示按需加载,此处具体情况需要具体分析

<van-tabbar-item info="{{item.info>0?item.info:''}}" wx:for="{{list}}" wx:key="name">

7.如果徽标显示溢出tabBar容器

在index.scss中设置以下: 将margin-bottom设置为0

.van-tabbar-item{
  // scss中变量使用$开头
  $tabbar-item-margin-bottom: 0
}

注意:index.ts中需要设置以下才会生效

  options:{
    "styleIsolation":"shared"
  },

 

8.使用mobx 将徽标的值设置为 动态可变

测试案例:将numA,numB,sum放在store中,numA或者numB改变时,sum计算属性对应改变,然后将sum值和info做同步。

store.ts:

import { observable, action} from 'mobx-miniprogram'

export const store = observable({
  numA: 1,
  numB: 2,
  active: 0,

  get sum(){
    return this.numA + this.numB;
  },
  updateActive:action(function(this: any, active:number){
    this.active = active;
  }),
  updateNumA: action(function(this: any, step:number){
    this.numA += step;
  }),
  updateNumB: action(function(this: any, step:number){
    this.numB += step;
  })

});

home页面展示对应值和两个改变值按钮,改变后,同步index中的徽标属性info

home.wxml:

<view>
<view>
  {{numA}} + {{numB}}  = {{sum}}
</view>
  <van-button type="primary" bindtap="handleNumA" data-step="1"> numA + 1 </van-button>
  <van-button type="info" bindtap="handleNumA" data-step="-1"> numA - 1 </van-button>
</view>
// pages/home/home.ts
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'

Page({

  /**
   * 页面的初始数据
   */
  data: {

  },
  handleNumA(this:any, e: any){
    this.updateNumA(e.target.dataset.step-0);
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(this: any) {
    this.storeBindings = createStoreBindings(this,{
      store,
      fields:['numA','numB','sum'],
      actions:['updateNumA']
    });

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload(this: any) {
    this.storeBindings.destroyStoreBindings();
  },

})

 然后再index.ts中监听sum变化,并同步info值

observers:{
    'sum':function(val){
      this.setData({ 'list[0].info': val });
    }
  },

9.实现tabBar页面可切换

<van-tabBar>标签中设置onChange事件通过e.detail回去当前tabBar索引,并调用wx.switchTab()切换到对应页面

<van-tabbar active="{{ active }}" bind:change="onChange"
active-color="#07c160">
  methods: {
    onChange(this:any,e: any){
      // 切换tab页面
      // 将active保存到store中,否则点中项会错乱
      // this.setData({ active: e.detail });
      this.updateActive(e.detail);
      wx.switchTab( {url: this.data.list[e.detail].pagePath} );
    }
  }
})

 11.选中项索引active直接赋值e.detail会混乱,将索引存到store中

store.ts:

export const store = observable({
...
  active: 0,

...
  updateActive:action(function(this: any, active:number){
    this.active = active;
  }),
})

index.ts中再调用updateActive()方法改变active的值 

  methods: {
    onChange(this:any,e: any){
      // 将active保存到store中,否则点中项会错乱
      // this.setData({ active: e.detail });
      this.updateActive(e.detail);
      wx.switchTab( {url: this.data.list[e.detail].pagePath} );
    }
  }
})

12.改变选中项文字颜色

 <van-tabbar>中设置active-color="#07c160"为想要的颜色即可

13.注意:app.json中list中的页面及路径等必须和自定义tabBar自定义组件中的数据相同

data: {
    // active: 0,
    // list的pagePath: "/pages/home/home"必须再app.json中有对应数据
    list:[{
      info:3,
      name:"首页",
      pagePath: "/pages/home/home",
      icon: {
        normal: '/images/tabs/home.png',
        active: '/images/tabs/home-active.png',
      },
    },{
      name:"消息",
      pagePath: "/pages/message/message",
      icon: {
        normal: 'https://img.yzcdn.cn/vant/user-inactive.png',
        active: 'https://img.yzcdn.cn/vant/user-active.png',
      },
    },{
      name:"联系我们",
      pagePath: "/pages/contact/contact",
      icon: {
        normal: 'https://img.yzcdn.cn/vant/user-inactive.png',
        active: 'https://img.yzcdn.cn/vant/user-active.png',
      },
    }
  ],
  },

14.完整代码

代码结构:

 

app.json

{
  "pages": [
    "pages/home/home",
    "pages/message/message",
    "pages/contact/contact"
  ],
  "subpackages": [{
    "root": "packageA",
    "pages": ["pages/basic/basic","pages/logs/logs"]
  },{
    "root": "packageB",
    "pages": ["pages/test1/test1","pages/test2/test2"],
    "independent": true
  }
],
"preloadRule": {
  "packageA/pages/basic/basic":{
    "network": "wifi",
    "packages": ["packageA"]
  }
},
  "tabBar": {
    "custom": true,
    "list": [{
      "pagePath": "pages/home/home",
      "text": "首页",
      "iconPath": "/images/tabs/home.png",
      "selectedIconPath": "/images/tabs/home-active.png"
    },{
      "pagePath": "pages/message/message",
      "text": "消息",
      "iconPath": "/images/tabs/message.png",
      "selectedIconPath": "/images/tabs/message-active.png"
    },{
      "pagePath": "pages/contact/contact",
      "text": "联系我们",
      "iconPath": "/images/tabs/contact.png",
      "selectedIconPath": "/images/tabs/contact-active.png"
    }]
  },
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "Weixin",
    "navigationBarTextStyle": "black"
  },
  "sitemapLocation": "sitemap.json",
  "usingComponents": {
    "van-button": "@vant/weapp/button/index",
    "store-test": "/components/store-test/store-test",
    "van-tabbar": "@vant/weapp/tabbar/index",
    "van-tabbar-item": "@vant/weapp/tabbar-item/index"
  }
}

store.ts:

import { observable, action} from 'mobx-miniprogram'

export const store = observable({
  numA: 1,
  numB: 2,
  active: 0,

  get sum(){
    return this.numA + this.numB;
  },
  updateActive:action(function(this: any, active:number){
    this.active = active;
  }),
  updateNumA: action(function(this: any, step:number){
    this.numA += step;
  }),
  updateNumB: action(function(this: any, step:number){
    this.numB += step;
  })

});

home.wxml:

<!--pages/home/home.wxml-->
<text>pages/home/home.wxml</text>
<view>
<view>
  {{numA}} + {{numB}}  = {{sum}}
</view>
  <van-button type="primary" bindtap="handleNumA" data-step="1"> numA + 1 </van-button>
  <van-button type="info" bindtap="handleNumA" data-step="-1"> numA - 1 </van-button>
</view>

home.ts:

// pages/home/home.ts
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'

Page({

  /**
   * 页面的初始数据
   */
  data: {

  },
  handleNumA(this:any, e: any){
    this.updateNumA(e.target.dataset.step-0);
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(this: any) {
    this.storeBindings = createStoreBindings(this,{
      store,
      fields:['numA','numB','sum'],
      actions:['updateNumA']
    });

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload(this: any) {
    this.storeBindings.destroyStoreBindings();
  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

index.wxml:

<van-tabbar active="{{ active }}" bind:change="onChange"
active-color="#07c160">
  <van-tabbar-item info="{{item.info>0?item.info:''}}" wx:for="{{list}}" wx:key="name">
    <image
      slot="icon"
      src="{{ item.icon.normal }}"
      mode="aspectFit"
      style="width: 30px; height: 18px;"
    />
    <image
      slot="icon-active"
      src="{{ item.icon.active }}"
      mode="aspectFit"
      style="width: 30px; height: 18px;"
    />
    {{item.name}}
  </van-tabbar-item>
</van-tabbar>

index.ts:

import { ComponentWithStore } from 'mobx-miniprogram-bindings'
import { store } from '../store/store'

ComponentWithStore({
  options:{
    "styleIsolation":"shared"
  },
  observers:{
    'sum':function(val){
      this.setData({ 'list[0].info': val });
    }
  },
  storeBindings:{
    store,
    // 只需要监听sum所以只引入sum
    fields:['sum','active'],
    actions:['updateActive']
  },
  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    // active: 0,
    // list的pagePath: "/pages/home/home"必须再app.json中有对应数据
    list:[{
      info:3,
      name:"首页",
      pagePath: "/pages/home/home",
      icon: {
        normal: '/images/tabs/home.png',
        active: '/images/tabs/home-active.png',
      },
    },{
      name:"消息",
      pagePath: "/pages/message/message",
      icon: {
        normal: 'https://img.yzcdn.cn/vant/user-inactive.png',
        active: 'https://img.yzcdn.cn/vant/user-active.png',
      },
    },{
      name:"联系我们",
      pagePath: "/pages/contact/contact",
      icon: {
        normal: 'https://img.yzcdn.cn/vant/user-inactive.png',
        active: 'https://img.yzcdn.cn/vant/user-active.png',
      },
    }
  ],
  },

  /**
   * 组件的方法列表
   */
  methods: {
    onChange(this:any,e: any){
      // 切换tab页面
      // 将active保存到store中,否则点中项会错乱
      // this.setData({ active: e.detail });
      this.updateActive(e.detail);
      wx.switchTab( {url: this.data.list[e.detail].pagePath} );
    }
  }
})

index.scss:

/* custom-tab-bar/index.wxss */
.van-tabbar-item{
  // scss中变量使用$开头
  $tabbar-item-margin-bottom: 0
}

15.效果实现 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值