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"><imageslot="icon"src="{{ item.icon.normal }}"mode="aspectFit"style="width: 30px; height: 18px;"/><imageslot="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"><imageslot="icon"src="{{ item.icon.normal }}"mode="aspectFit"style="width: 30px; height: 18px;"/><imageslot="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所以只引入sumfields:['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.效果实现