tabbar #
tabbar 提供了自定义 tabbar 的UI以及包含子组件与跳转的能力。
可以基于自定义的tabbar,实现不同的tabbar需求,以及动画能力。
使用 #
以下代码并不是完整的代码。具体使用请看 nPro 的demo。
<template>
<view>
<n-tabbar ref="tabbar" :tabs="tabs" :tabStyle="tabStyle" @tabClicked="tabbarSwitched">
<home></home>
<mine></mine>
</n-tabbar>
<plus :show="plusVisible" @cancel="toHidePlus"></plus>
</view>
</template>
import home from './home.vue'
import mine from './mine.vue'
import plus from './plus.vue'
import navHelper from '@/service/navHelper.js'
export default {
components: {
home,
mine,
plus
},
mixins: [navHelper],
provide() {
return {
tabRoot: this
}
},
data() {
return {
plusVisible: false,
tabs: [
{
icon: '/static/tabs/home.png',
selectedIcon: '/static/tabs/homeH.png',
title: '首页',
selectedTitle: '首页'
},
{
icon: '/static/tabs/plus.png',
selectedIcon: '/static/tabs/plus.png',
title: '',
selectedTitle: '',
iconBoxWidth: '76px',
iconStyle: 'width: 60px;height:38px;',
selectedIconStyle: 'width: 60px;height:38px;',
noPage: true
},
{
icon: '/static/tabs/mine.png',
selectedIcon: '/static/tabs/mineH.png',
title: '我的',
selectedTitle: '我的'
}
],
tabStyle: {
iconStyle: 'width:22px;height:22px;',
selectedIconStyle: 'width:22px;height:22px;',
titleStyle: 'font-size:12px;color:#999999;',
selectedTitleStyle: 'font-size:12px;color:#875F3C;',
boxStyle: 'border-top-width:0.5px;border-top-color:#DDDDDD;border-top-style:solid;'
}
}
},
onLoad(option) {
const app = getApp({allowDefault: true})
if (option.target) {
const target = option.target
const toTab = target * 1
// switch with no animation
setTimeout(()=>{
this.$refs.tabbar.setPage(toTab, false)
}, 50)
} else {
app.globalData.currentTab = 0
}
},
methods: {
tabbarSwitched(val) {
if (val.page === 1) {
this.plusVisible = true
return
}
// 记录当前tab
const app = getApp({allowDefault: true})
if (!app) return;
app.globalData.currentTab = val.page * 1
},
toHidePlus() {
this.plusVisible = false
}
}
}
以上例子就是一个包含 三个tabItem,其中一个 tabItem 是弹窗形式的 自定义的tabbar。
上面的tabbar包含了两个子组件,分别是 主页和我的。我们的 tabs 设置中设置了 三个tabItem。其中一个是 noPage 形式,也就是不占用子组件。
我们的 plus 组件对应的就是 noPage 设置。plus 组件是一个弹窗。您可以想象一下, 主页/我的,然后中间一个大大的 + 号。不管你处在哪个页面,点击这个 + 号都会弹出一个全屏的弹层,让您具备其它选择的能力。
这是很常用的一种设计。我想你也一定能 get 到这个意思。
tabbar 及其包裹的子组件定义了页面的内容,正如我们所看到的,他们都是在一个页面里面。我们需要管理当前处于哪个tab,又要去往哪个tab。
在 tabbar 外层的组件,一般都是一些 toast/loading/popup 之类等。毕竟 tabbar 会占满全屏。剩下的也只够您 弹出内容了。
使用 tabbar,最重要的就是:tabbar的UI适配,和 tabbar的功能跳转,以及 tab内容与页面之间的通信。
UI适配 #
对于 tabs的设置,我们提供了 tabStyle 这个全局的样式设置,也允许您在 tabs 中为某个tab做个性化的配置。
tabStyle #
统一样式配置入口。可配置的属性如下:
{
iconStyle: 'font-size: 20px;color: #333232;', // 图标样式,是icon字体的话,可以设置字体大小和颜色。一般我们用图片
selectedIconStyle: 'font-size: 20px;color: #01A9F0;', // 选中时的icon样式,字体的话是大小和颜色
titleStyle: '', // tabitem的文字样式
selectedTitleStyle: '', // 选中是tabitem的文字样式
boxStyle: '', // tabs的外层style设置
itemStyle: '', // 每个item的外层style
height: 50, // tabbar的tabs高度。Number类型。px
badgeStyle: '', // badge为text时的外层style
badgeTextStyle: '', // badge text的样式
dotStyle: '', // badge为dot时的style
// we use it to help to position the badge or dot
iconBoxWidth: '46px', // 我们为图标设置一个盒子宽度,方便定位 badge。您的badge是依据此宽度来定位的
image: null, // 背景图片。一般我们只设置最上边的那个特殊弧度的背景
imageStyle: '', // 背景图片的样式
imageBoxStyle: '', // 背景图片外层的样式
}
height 以及 iconBoxWidth 不设置的话,默认分别是 50 46px。没有什么是必须要设置的,您根据需要设置显示的内容。
tabs #
tabs 是一个数组,决策了 有多少个 tabs,以及他们各自的功能、定制化的样式。每个tabitem的具体配置如下:
{
icon: '', // 图标,一般是图片,可以是字体图标
selectedIcon: '', // 选中时icon
title: '', // 文字
selectedTitle: '', // 选中时文字。为空表示选中时不显示文字
badge: 0, // badge 的数字
dot: false, // 是否显示成 dot 圆点
isHump: false, // 是否凸出。默认是 false
noPage: false, // 是否不在切换页面之中。默认是false
humpStyle: '', // 凸出的style。设置凸起宽高
humpBottom: '', // 凸起距离底部的距离,设置凸起偏移量
iconStyle: '', // 图标样式
selectedIconStyle: '', // 图标样式
titleStyle: '', // 文字样式
selectedTitleStyle: '', // 文字样式
badgeStyle: '', // badge外层样式
badgeTextStyle: '', // badge文字样式
dotStyle: '', // dot样式
iconBoxWidth: '' // 图标外层宽度,方便定位 badge/dot
}
具体的tabbar样子与适配代码,请看nPro的demo代码。

Props #
| Prop name | Description | Type | Values | Default |
|---|---|---|---|---|
| tabs | tabs 的内容以及个性化的配置。 isHump 表示是否凸起, noPage 表示点击当前 tab 时不切换,依然停留在原 tab 内容。 hump 具备 humpStyle,hump 有 humpBottom(就是距离底部的距离 px)。 icon,selectedIcon,title,selectedTitle, badge,dot, isHump,noPage,humpStyle,humpBottom iconStyle,selectedIconStyle,titleStyle,selectedTitleStyle, badgeStyle,badgeTextStyle,dotStyle,iconBoxWidth | array | - | |
| tabStyle | 全局 tabs 的样式设置。tabs 中可以单独设置进行覆盖 | object | - | { iconStyle: 'font-size: 20px;color: #333232;', selectedIconStyle: 'font-size: 20px;color: #01A9F0;', titleStyle: '', selectedTitleStyle: '', boxStyle: '', tabsStyle: '', itemStyle: '', height: 50, // px badgeStyle: '', badgeTextStyle: '', dotStyle: '', // we use it to help to position the badge or dot iconBoxWidth: '46px', image: null, imageStyle: '', imageBoxStyle: '', imageWidthXBar: false } |
| duration | 页面切换的动画周期 | number | - | 300 |
| timingFunction | 页面切换的动画函数 | string | - | 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' |
| top | 距离顶部的距离 | string | - | '0' |
| isSeize | tabs 以及 xbar 的高度是否有占位 | boolean | - | true |
| considerXBar | 是否考虑 xbar | boolean | - | true |
| xBarBgType | xbar 的背景主题 | string | - | 'inverse' |
| xBarStyle | xbar 的样式 | string | - | '' |
Events #
| Event name | Properties | Description |
|---|---|---|
| tabClicked |
Slots #
| Name | Description | Bindings |
|---|---|---|
| default | ||
| bg | ||
| tabs |
事件跳转 #
我们对外提供了,next prev setPage 三个 ref method,用于您做程序内跳转。
next 与 prev 是 setPage 的便捷方法,我们一般不使用,主要还是使用 setPage。
setPage #
setPage(page, animated = true)
点击 tabitem,自动调用了该方法,该方法会帮您处理 内容子组件的切换,同时给您一个 tabClicked 通知。
您需要监听该通知 @tabClicked,来记录您的当前 tab number,以便实现更多的业务逻辑。该通知携带参数格式为:{page: 1}。
@tabClicked #
点击 tabitem,以及调用 setPage 都会触发 tabClicked 通知。该通知携带参数格式为:{page: 1}。
程序跳转 #
setPage(page, animated = true)
外部API接口跳转,请直接跳用该ref method。
- page 为当前的页码,从 0 开始,hump/noPage 也是计数的;
- animated 为是否需要动画效果,默认是开启的。
一般在哪里用到api跳转?
onLoad 里面,我们可能需要一个app打开,默认就处在 第二个 tabitem,这需要我们自己调用接口设置。
动态内容 #
动态内容,主要是指 tabitem 的动态,其中包括,tabitem的设置动态,以及 tabitem的数量动态。
动态tab内容 #
我们的 badge/dot 之类的东西,一般都是 动态的,您只需要恰当的处理好数据的变化就行。
您肯定有一些机制来让自己知道 badge/dot 改变了,随即去更新 tabs 的内容即可。
关于 tabitem 的样式动态,实际上也是可以的。您完全可以动态的改变样式属性配置,来实现动态的样式。
动态tab数量 #
有些人可能想实现,三个 tabitem 的页面,执行某个操作之后,页面变成 2个tabitem,比如 切换用户身份后,或者进入新的使用模式。
这也是可以的。不过我们并不建议在该 tabbar 页面直接改变,我们希望您 直接relaunch跳转到另一个具备不同 tabbar 的页面。
通信 #
由于 tabbar 是一个组件,各个页面的内容其实是 tabbar 的子组件,几个 tabitem 的内容其实都在 一个页面里面。也就是就只具备一个 onLoad onShow 等页面的生命周期,其它的的内容都是组件生命周期。
很多业务的处理可能都需要 移交到 具备页面生命周期的 那个承载页面 来做处理。
这就需要用到很多的通信或者通知监听。
常用的 父子组件通信/页面通信/全局变量 等方法都可以使用。
组件级emit/on #
有个时候,层次不是很高,我们可以直接使用 emit/on 进行父子组件事件通知与监听。
provide/inject #
使用 provide/inject 避开深层次的 emit/on。
watch/vuex #
有时候业务复杂,比如,用户登陆之后,各个 tabitem的内容都需要刷新,怎么办?
各自 watch vuex 中的同一个值,执行相应的业务逻辑。
全局 emit/on #
比如,我在某一个 发帖的页面,首页是一个帖子列表,我发帖之后需要刷新首页,怎么办?
可以使用 全局的 uni.$emit uni.$on。当然,记得在必要的时候 uni.$off。
其它设置 #
duration #
tab内容切换的动画周期,默认 300ms。
timingFunction #
tab内容切换的动画曲线,默认 cubic-bezier(0.25, 0.46, 0.45, 0.94)