Taro小程序开发 自定义tabBar 实现的思路于步骤

1,459 阅读3分钟
思路: 
自己封装一个组件,在每个tabBar页面引入该组件,为了解决在不同的页面切换tabBar时需要2次才能成功的问题,
这里采用了在引入该组建的时候就告知组件需要高亮的tab,以及传入该tab在权限列表中位置,
因为每一个tab页面都需要获取相关的权限所以可以提前拿到权限列表包括在该tab在权限列表中的位置。
由于react的更新机制,传入值组件不能立马更新,
这里给组件添加了一个立即更新的key值 (key={ new Date().getTime() })来解决这个问题。
还有一点就是每个tab页面先请求权限,然后组件再请求权限,
为了解决组件初始时请求还没结束权限列表为空而导致的闪烁问题,
这里采用将每个tab请求存储在本地的权限数据,在每次组件请求的时候先将本地已经存在的权限暂时赋值给组件,
请求成功之后在清空数据再赋值。
1. 全局设置tabBar 位自定义模式
customer: true

image-20230201150514858.png

2. 为了更好对底部的tabBar进行权限控制 不同角色进入 显示不同的 tabBar, 以及更好的自定义样式。
故采用了自己封装组件的方式,在每一个tabbar页面引入该组件。
​
在主包pages下创建 customerTab文件加以及包含的文件如下图

image-20230201150926114.png

import { Component } from 'react'
import Taro from '@tarojs/taro'
import { AtTabBar }  from 'taro-ui'
import request from '../../utils/request';
​
import "taro-ui/dist/style/components/tab-bar.scss"
import "taro-ui/dist/style/components/badge.scss"
import "taro-ui/dist/style/components/icon.scss";
import './index.scss'export default class CustomerTab extends Component {
    constructor () {
        super(...arguments)
        const { tabIndex } = arguments[0]
        this.state = {
            current: tabIndex,
            tabIndex:tabIndex,
            tabList: []
        }
    }
    componentWillMount () {
        const { uid, hxUserId } =  Taro.getStorageSync('taro_authentica')
        this.getRightTab()
    }
    handleClick (value) {
        console.log('tabIndex', this.state.tabList, value);
        const jumpUrl = this.state.tabList[value].url
        Taro.switchTab({
            url: jumpUrl
        })
    }
    async getRightTab(){
        /**
         * 在每个tab页面获取权限时候都需要存储有哪些权限
         * 在这个页面再次获取权限的时候提权将数据初始化否则
         * tabBar会闪烁
        */
        const newRightsData = Taro.getStorageSync('taro_rights_data') || []
        console.log('newRightsData',newRightsData);
        let haveTablist =[]
        if(newRightsData && newRightsData.length>0){
            newRightsData.forEach((item)=>{
                switch (item.fname) {
                    case '首页':
                        haveTablist.push({
                            title: '首页',
                            image:'填写自己默认图片',
                            selectedImage:'填写自己选中图片',
                            url: '/pages/index/index'
                        }) 
                        break;
                    case '任务':
                        haveTablist.push({
                            title: '任务',
                            image:'填写自己默认图片',
                            selectedImage:'填写自己选中图片',
                            url: '/pages/tabBar/index'
                        }) 
                        break;
                    case '客户':
                        haveTablist.push({
                            title: '统计',
                            image:'填写自己默认图片',
                            selectedImage:'填写自己选中图片',
                            url: '/pages/statisticsManage/index'
                        }) 
                        break;
                    default:
                        break;
                }
            })
        }
        // 一个tab,不显示tabBar
        if(haveTablist.length<2){
            this.setState({
                tabList: [],
            })
        }else {
            this.setState({
                tabList:  haveTablist
            })
        }
        /**
         * 以下看似相同的操作目的是为了刷新权限变化更新
         * 即使权限没有变化以下操作也无其他影响
         */
        const { uid, hxUserId } =  Taro.getStorageSync('taro_authentica')
        let params = {
            uid,
            platformCode:'YSB_MINI_APP',
        }
        // request 是自己封装的请求方式
        await request(`获取权限的接口`, 'get', params)
        .then((res) => {
            const { result, msg, data } = res.data;
            let tabList=[]
            if(result==0){
                console.log('data',data);
                data.forEach((item)=>{
                    switch (item.fname) {
                        case '首页':
                            tabList.push({
                                title: '首页',
                                image:'填写自己默认图片',
                                selectedImage:'填写自己选中图片',
                                url: '/pages/index/index'
                            }) 
                            break;
                        case '任务':
                            tabList.push({
                                title: '任务',
                                image:'填写自己默认图片',
                                selectedImage:'填写自己选中图片',
                                url: '/pages/tabBar/index'
                            }) 
                            break;
                        case '客户':
                            tabList.push({
                                title: '统计',
                                image:'填写自己默认图片',
                                selectedImage:'填写自己选中图片',
                                url: '/pages/statisticsManage/index'
                            }) 
                            break;
                        default:
                            break;
                    }
                })
                // 一个tab,不显示tabBar
                if(tabList.length<2){
                    this.setState({
                        tabList: [],
                    })
                }else {
                    this.setState({
                        tabList:tabList ,
                    })
                }
            }
        })
        .catch((_err) => {
            Taro.hideLoading()
        });
    }
    render () {
        return (
            <AtTabBar
                fixed
                fontSize="12"
                tabList={ this.state.tabList }
                onClick={ this.handleClick.bind(this) }
                current={ this.state.current }
            />
        )
    }
}
该组件就是获取后台配置的权限,显示对应的tabBar按钮。
但是有一点需要注意的是 为了在不同页面引入该组件 并且在切换不同tab的不需要切换2次才高亮,
这里采用的是组件在引用的时候也需要传入期望被选中的tab的index(也就是该tab在权限列表中的位置)
在tab页 引入该组件

image-20230201152428068.png

其中selectIndex 就是 该tab在权限列表的中位置
​
其中没个tabBar都需要请求该tab的相关权限 在获取成功的时候 向本地或者全局存储该用户的权限列表
Taro.setStorageSync('taro_rights_data',data)
​
在每一个tab的 Taro.useDidShow 中获取该tab的位置 并且赋值给 selectIndex
Taro.useDidShow(() => {
    const newRightsData = Taro.getStorageSync('taro_rights_data') || []
    let findIndex=  newRightsData.findIndex(item=>item.fname=='任务')
    console.log('findIndex', findIndex);
    setselectIndex(findIndex)
})
​
但是由于react的更新机制不是立马更新 但是我们期望他立即更新 所以我们给组件添加 
new Date().getTime() 的key来实现实时更新组件