本文内容主要来自 Taro 文档 微信小程序自定义 Tabbar,在使用过程中一些小优化。
按照文档说明,需要先在 app.config.ts
配置文件中 tabBar
字段中添加 custom: true
,启用自定义 tabbar,list
需至少包含 2 项,不必全部填写完,后面在自定义 tabbar 组件里维护具体导航信息。
第二步在项目 src
目录下创建 custom-tab-bar
文件夹。
|-- custom-tab-bar
|-- -- index.config.ts
|-- -- index.scss
|-- -- index.tsx
|-- -- useCustomTabBar.ts
// custom-tab-bar/index.config.ts
// 声明当前文件夹是一个组件
export default {
component: true,
}
// custom-tab-bar/index.tsx
import { View } from '@tarojs/components'
import { switchTab } from '@tarojs/taro'
import { Component } from 'react'
import { joinClassNames } from '~/utils'
import './index.scss'
export default class CustomTabBar extends Component<
{},
{
/** tabbar 高亮的索引,默认不给值,有初始值会造成闪动 */
selected?: number
/** tabbar 是否可见,配合页面需求隐藏。自定义 tabbar 被包裹在 tab-bar 标签下,一般元素的 z-index 值不易覆盖 */
visible: boolean
}
> {
state = {
selected: undefined,
visible: true,
list: [
{
pagePath: '/pages/index1/index',
text: 'tab1',
},
{
pagePath: '/pages/index2/index',
text: 'tab2',
},
{
pagePath: '/pages/index3/index',
text: 'tab3',
},
],
}
switchTab(index: number, url: string) {
if (index !== this.state.selected) {
switchTab({ url })
}
}
setSelected(idx: number) {
this.setState({
selected: idx,
})
}
toggle(visible: boolean) {
this.setState({
visible,
})
}
render() {
const { list, selected, visible } = this.state
return (
<View className={joinClassNames('tab-bar', visible ? null : 'hidden')}>
<View className="tab-bar-border" />
{list.map((item, index) => {
const isActived = selected === index
return (
<View
key={index}
className="tab-bar-item"
onClick={this.switchTab.bind(this, index, item.pagePath)}>
<View
className={joinClassNames(
'tab-bar-item-text',
isActived ? 'active' : null,
)}>
{item.text}
</View>
</View>
)
})}
</View>
)
}
}
// custom-tab-bar/useCustomTabBar.ts
import { useDidShow, getCurrentInstance, getTabBar } from '@tarojs/taro'
import { useCallback } from 'react'
import type CustomTabBar from './'
export const useCustomTabBar = (n: number) => {
const pageCtx = getCurrentInstance().page
useDidShow(() => {
// 每个 tab 页下的自定义 tabBar 组件实例是不同的,来源:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html
// 每次切换回 tab 页面就激活对应 tab。
const tabBar = getTabBar<CustomTabBar>(pageCtx)
tabBar?.setSelected(n)
})
const toggle = useCallback(
(visible: boolean) => {
const tabBar = getTabBar<CustomTabBar>(pageCtx)
tabBar?.toggle(visible)
},
[pageCtx],
)
return { toggle }
}
每个 tabbar 配置的页面如下使用
import { View } from '@tarojs/components'
import { useCustomTabBar } from 'path/custom-tab-bar/useCustomTabBar'
export default function PageIndex() {
// 根据页面在 tabbar 的顺序指定高亮下标
useCustomTabBar(0)
return <View>PageIndex</View>
}
注意事项
一 页面高度
系统自带的 tabbar 会自动占用部分高度,自定义 tabbar 只是 fixed
布局,需要页面主动留住自定义 tabbar 高度。
二 弹出层如何盖住自定义 tabbar
例如淘宝购物车切换 sku 的弹出层可以全屏显示,默认情况微信小程序这样的弹出层会被自定义导航栏盖住,目前有两个方式实现完整显示弹出层。
1 配合 useCustomTabBar
返回的 toggle
手动控制自定义 tabbar 出现、隐藏。2 经过尝试,把弹出层的 z-index
设置到 10000
以上的数值可以覆盖 tab-bar 元素。