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.效果实现