使用Taro实现自定义Tabbar遇到切换页面和高亮不同步问题

1,655 阅读2分钟

1. Taro实现自定义Tabbar

平时在开发时会遇到一些Tabbar中间有悬浮按钮的需求,比如这样

image.png 这时候就需要自定义底部Tabbar,按照官方文档,我们可以这样操作

1.修改app.config配置

tabBar: {
    selectedColor: themeVars.nutuiColorPrimary,
    borderStyle: 'white',
    custom: true,
    list: [
      {
        pagePath: 'pages/index/index',
        text: '首页',
        iconPath: 'assets/images/home.png',
        selectedIconPath: 'assets/images/home-s.png',
      },
      {
        pagePath: 'pages/my/my',
        text: '我的',
        iconPath: 'assets/images/user.png',
        selectedIconPath: 'assets/images/user-s.png'
      }
    ]
  },

image.png

2.在src新建目录和文件

image.png

3.然后我们在index.tsx中填入我们的组件内容

import  { useEffect, useState } from 'react'
import { View } from '@tarojs/components';
import { Button, Image } from '@nutui/nutui-react-taro';
import './index.scss'
import ThemeProvider from '@/theme-provider/ThemeProvider';
import { themeVars } from '@/theme-provider/theme.config';
import Taro from '@tarojs/taro';
// import { useTabBarStore } from '@/store';

function CustomTabBar() {
  const [curentIndex, setCurrentIndex] = useState(0)
  // const {selectTab,setSelectTab} = useTabBarStore()
  const list = [
      {
        pagePath: '/pages/index/index',
        text: '首页',
        iconPath: '/assets/images/home.png',
        selectedIconPath: '/assets/images/home-s.png',
      },
      {
        pagePath: '/pages/my/my',
        text: '我的',
        iconPath: '/assets/images/user.png',
        selectedIconPath: '/assets/images/user-s.png'
      }
    ]
  return (
    <ThemeProvider>
      <View className='tab-bar'>
        <View style={{ display: 'flex', justifyContent: 'space-around', alignItems: 'center', width: '100%',paddingTop: '5px' }}>
          {
            list.map((item,index) => (
              <View className='tab-bar-item' key={index} onClick={ () => {
                 setCurrentIndex(index)
                 Taro.switchTab({ url: item.pagePath })  // 跳转到指定页面
              }} >
                <Image src={index === curentIndex ? item.selectedIconPath : item.iconPath} />
                <View style={{ marginTop: 5, color: index === curentIndex ? themeVars.nutuiColorPrimary : '#999' }}>{item.text}</View>
              </View>))          
          }
          <Button className='middle-btn'>1</Button>
        </View>
      </View>
    </ThemeProvider>
  )
}

export default CustomTabBar

这里要注意list从原来的app.config复制过来的,需要改些目录,比如pagePath在app.config里开头是不需要/,但是这里需要

image.png 这里实现底部Tabbar凹陷形状的思路狠简单粗暴,直接拿背景图进行覆盖,然后按钮定位上去,这里就不细讲。 当完成了基本的Tabbar之后是这样的

image.png 然后就遇到了一个问题

2. 底部Tabbar切换页面和高亮不同步

意思就是说,当我点击某个tab时,会立即切换页面,但是并不高亮,只有我再次点击这个tab才会高亮,如图,

recording.gif 这个问题其实是因为我们的切换页面后状态会重新执行,这个地方用全局状态就可以解决,我这里之前用了zustand,所以这里还是只用zustand进行全局状态管理

1.新建useTabBarStore.ts文件,填入如下代码

import { create } from "zustand";

interface IuseTabBarStore {
    selectTab: number;
    setSelectTab: (selectTab: number) => void;
}

const useTabBarStore = create<IuseTabBarStore>((set) => ({
    selectTab: 0,
    setSelectTab: (selectTab: number) => set({ selectTab }),
}))

export default useTabBarStore;

2.然后就完美解决了

image.png

import  { useEffect, useState } from 'react'
import { View , Image} from '@tarojs/components';
import { Button } from '@nutui/nutui-react-taro';
import './index.scss'
import ThemeProvider from '@/theme-provider/ThemeProvider';
import { themeVars } from '@/theme-provider/theme.config';
import Taro from '@tarojs/taro';
import { useTabBarStore } from '@/store';

function CustomTabBar() {
  const {selectTab,setSelectTab} = useTabBarStore()
  const list = [
      {
        pagePath: '/pages/index/index',
        text: '首页',
        iconPath: '/assets/images/home.png',
        selectedIconPath: '/assets/images/home-s.png',
      },
      {
        pagePath: '/pages/my/my',
        text: '我的',
        iconPath: '/assets/images/user.png',
        selectedIconPath: '/assets/images/user-s.png'
      }
    ]
  return (
    <ThemeProvider>
      <View className='tab-bar'>
        <View style={{ display: 'flex', justifyContent: 'space-around', alignItems: 'center', width: '100%',paddingTop: '5px' }}>
          {
            list.map((item,index) => (
              <View className='tab-bar-item' key={index} onClick={ () => {
                 setSelectTab(index)
                 Taro.switchTab({ url: item.pagePath })  // 跳转到指定页面
              }} >
                <Image src={index === selectTab ? item.selectedIconPath : item.iconPath} style={{ width: 24, height: 24 }}/>
                <View style={{ marginTop: 5, color: index === selectTab ? themeVars.nutuiColorPrimary : '#999' }}>{item.text}</View>
              </View>))          
          }
          <Button className='middle-btn'>1</Button>
        </View>
      </View>
    </ThemeProvider>
  )
}

export default CustomTabBar

recording.gif