# 可对应切换路由的页签

组件来源:办公系统v3 - 一般组件

## 1.功能说明

一组多选标签，点击某个标签后,可对应切换页面路由

## 2.组件依赖

- react

- antd

- react-router-dom

## 3.依赖结构体

由于其可切换路由的特殊性，我们可能会在不同的组件中调用此通用组件，为了保证不同组件中的标签一致，该组件需要依赖上下文。

```tsx
export interface TabRoute {
    title: string          //标签展示的名称
    themeColor?: string    //标签主题颜色
    url: string            //标签跳转路由的url
    closable?: boolean     //标签是否可关闭
    popConfirm?: boolean   //标签的气泡弹窗，默认没有
    closeCallbackFn?: (tab: TabRoute) => Promise<any>  //关闭标签的回调
}

//组件上下文接口
export interface CommonTabbarState {
    routes: TabRoute[],    //所有标签列表
    themeColor: string,    //整体主题颜色
    setRoutesOverwrite: (value: TabRoute[]) => void,   //用来重置routes，赋予一个新的值
    pushRoute: (value: TabRoute) => void,              //向routes中添加一个值
    changeTheme: (value: string) => void,              //改变主题颜色themeColor
}
```

## 4.组件接口

```tsx
interface Iprops {
    context: React.Context<CommonTabbarState>    //公用标签上下文
    maxWidth?: string | number                   //单个标签的最大宽度
    id: string                                   //组件唯一性id，由于组件中有document.getElementById(props.id)步骤，这个id尽量不要与其他重复
    tabInpage?: number                           //标签url在路由中的第几层
}
```

## 5.案例

为了体现切换组件路由的功能，我们需要在项目中配置相关的代码

1)最外层的index.tsx文件，需要配置BrowserRouter

```tsx
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);
reportWebVitals();
```

2)App.tsx文件，需要配置路由跳转，需要配置上下文。具体的跳转路径可根据实际情况自己修改

```tsx
import { ConfigProvider } from 'antd';
import zhCN from 'antd/es/locale/zh_CN';
import './App.less';
import React from 'react';
import { CommonTabbarState, useCommonTabbarService } from './common/common-tabbar';
import { Navigate, Route, Routes } from 'react-router-dom';
import MainLayout from '@/layouts';

export const CommonTabbarContext = React.createContext<CommonTabbarState>(null);

function App() {
    return (
        <ConfigProvider locale={zhCN}>
            <CommonTabbarContext.Provider value={useCommonTabbarService()}>
                <div className="tn-base">
                    <Routes>
                        <Route path='/common/test/*' element={<MainLayout />} />
                        <Route path='/' element={<Navigate to={`/common/test`} />} />
                    </Routes>
                </div>
            </CommonTabbarContext.Provider>
        </ConfigProvider>
        )
}

export default App;
```

3)在src目录下创建layouts文件夹，在文件夹中添加index.tsx文件，src/layouts/index.tsx文件如下：

```tsx
import { useContext, useEffect } from "react";
import { CommonTabbarContext } from "@/App"; //引入App中定义的上下文
import CommonTabbar, { CommonTabbarState, TabRoute } from "@/common/common-tabbar";

const tabs: TabRoute[] = [
    {
        title: '个人设置',
        url: 'me',
        themeColor: '#FF5035',
    },
    {
        title: '任务设置',
        url: 'task',
        themeColor: '#FF5035',
        closable: true,
    },
]

export default function MainLayout() {
    const tabbarContext = useContext<CommonTabbarState>(CommonTabbarContext);
    useEffect(() => {
        //因为我们没有在其他地方对上下文赋值，这里在组件初始化的时候要为标签赋值，否则什么东西都不会有
        tabbarContext.changeTheme('FF5035');
        tabbarContext.setRoutesOverwrite(tabs);
    }, [])

    return (
        <div className="main-layout-container">
            <div className="project-layout-body">
                <CommonTabbar context={CommonTabbarContext} id="测试的tab" tabInpage={0}/>
                <PhotoPanel photos={photos}/>
            </div>
        </div>
    )
}
```

完成了上述三个文件的配置之后，页面便可显示标签了

## 5.备注

关于CommonTabbar的tabInpage属性的解释

CommonTabbar使用useNavigate进行跳转。tabInpage的默认值为0，表示在跳转的url前面添加的"../"的数量

假设现在路由为aaa/bbb/ccc/xxx，

当tabInpage = 0时，点击跳转url为yyy的页签会使用navigate("yyy")，此时会跳转至aaa/bbb/ccc/yyy

当tabInpage = 1时，点击跳转url为ttt/yyy的页签会使用navigate("../ttt/yyy")，此时会跳转至aaa/bbb/ttt/yyy

当tabInpage = 2时，点击跳转url为lll/ttt/yyy的页签会使用navigate("../../lll/ttt/yyy")，此时会跳转至aaa/lll/ttt/yyy

其余以此类推。

useNavigate文档： [useNavigate](https://reactrouter.com/en/main/hooks/use-navigate)
