掩于岁月的美妞 發表於 2023-10-17 10:04:00

React-Admin后台管理模板|react18+arco+zustand后台解决方案

<p><span style="font-size: 18px; font-family: 宋体, &quot;Songti SC&quot;; color: rgba(51, 102, 255, 1)">基于<span style="background-color: rgba(255, 255, 0, 1)">react18.x+vite4+arco-design</span>自研中后台管理系统解决方案<em>ReactAdmin</em>。</span></p>
<p><span style="font-size: 12px; font-family: &quot;comic sans ms&quot;, sans-serif"><strong>react-vite-admin</strong> 基于vite4搭建react18.x后台管理项目。使用了<span style="background-color: rgba(204, 255, 255, 1)">react18 hooks+arco.design+zustand+bizcharts</span>等技术实现权限管理模板框架。<span style="background-color: rgba(255, 255, 153, 1)">支持暗黑/亮色主题、i18n国际化、动态权限鉴定、3种布局模板、tab路由标签栏</span>等功能。</span></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017072301856-745073673.png"></p>
<p>React18Admin管理系统是<span style="color: rgba(51, 102, 255, 1)">首创自研</span>的轻量级中后台框架,构建运行速度快,支持<strong>dark/light</strong>主题模式。</p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017072758983-1277186941.png"></p>
<h3>技术栈</h3>
<ul>
<li><span style="font-size: 12px">编辑器:Vscode</span></li>
<li><span style="font-size: 12px">框架技术:react18+vite4+react-router+zustand+axios</span></li>
<li><span style="font-size: 12px">组件库:arco-design (字节前端react组件库)</span></li>
<li><span style="font-size: 12px">路由管理:react-router-dom^6.16.0</span></li>
<li><span style="font-size: 12px">状态管理:zustand^4.4.1</span></li>
<li><span style="font-size: 12px">模拟数据:mockjs^1.1.0</span></li>
<li><span style="font-size: 12px">模拟请求:axios^1.5.1</span></li>
<li><span style="font-size: 12px">图表库:bizcharts^4.1.22</span></li>
<li><span style="font-size: 12px">编辑器组件:@wangeditor/editor-for-react^1.0.6</span></li>
<li><span style="font-size: 12px">markdown编辑器:@uiw/react-md-editor^3.23.6</span></li>
<li><span style="font-size: 12px">请求进度插件:nprogress^0.2.0</span></li>
</ul>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017074532601-470803765.gif"></p>
<p>react-admin采用字节出品的react桌面端组件库<strong>arco.design</strong>。</p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017074924970-272121440.png"></p>
<h3>特性</h3>
<ol>
<li><span style="font-size: 12px">基于vite4.x构建react18后台,轻/快/小</span></li>
<li><span style="font-size: 12px">使用最新前端技术栈react18、zustand、bizcharts、react-router、axios</span></li>
<li><span style="font-size: 12px">搭配清新react组件库arco.design</span></li>
<li><span style="font-size: 12px">支持中英文/繁体国际化语言</span></li>
<li><span style="font-size: 12px">支持动态路由权限验证</span></li>
<li><span style="font-size: 12px">支持动态tabs标签栏控制</span></li>
<li><span style="font-size: 12px">内置多种模板布局样式</span></li>
</ol>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017075854606-1002673853.gif"></p>
<blockquote>
<h3><span style="background-color: rgba(255, 255, 153, 1); color: rgba(128, 0, 0, 1)">目前该react-admin后台管理模板,已经更新到我的原创作品集。</span></h3>
<p><span style="font-size: 12px">自研React18+ArcoDesign网页版后台管理admin系统</span></p>
</blockquote>
<h3>项目结构目录</h3>
<p>采用标准化的react目录结构,整个项目使用<em><strong>react18 function</strong></em>语法编码开发。</p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017081241955-2073966326.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017081356819-1165799555.gif"></p>
<h3>构建预览图</h3>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017081454676-1367984894.gif"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017081821809-520372854.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017081553638-310822205.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017081609079-240870084.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017081844916-1369157975.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017081920444-1493595489.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017081951565-362686758.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082014973-299907662.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082033627-1125072999.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082122223-113626874.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082151929-429513539.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082212471-1387548700.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082233874-1211621189.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082325791-480967834.png"></p>
<p><em>wangeditor-react</em>图文编辑器使用的是wangeditor的<strong>react</strong>版本,支持dark/light主题。</p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082347086-1540104961.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082443063-546347954.png"></p>
<p><em>react-md-editor</em>基于react的<strong>markdown编辑器</strong>,支持dark/light主题。</p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082719297-602930521.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017082733597-1173436593.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017083051336-1415793202.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017083137096-1269808678.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017083206744-605408524.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017083224231-2133513997.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017083248150-1965682863.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017083311275-2012365437.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017083332417-2144562792.png"></p>
<p>react18-scrollbar项目中使用的虚拟滚动条基于react18自定义组件实现功能。</p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017084324952-159579079.png"></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">// 引入滚动条组件
import RScroll from '@/components/rscroll'

</span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">RScroll </span><span style="color: rgba(255, 0, 0, 1)">autohide maxHeight</span><span style="color: rgba(0, 0, 255, 1)">={100}</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
    包裹需要滚动的内容块。。。
</span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">RScroll</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<h3>React18-Admin布局模板</h3>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017084519942-581809280.png"></p>
<p>如上图:支持<strong>分栏+垂直+水平</strong>3种通用布局模板。也可以定制化模板样式。</p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017084804366-1526972436.png"></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 主布局模板
* @author Hs Q:282310962
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

import { useMemo } from </span>'react'<span style="color: rgba(0, 0, 0, 1)">
import { appStore } from </span>'@/store/app'<span style="color: rgba(0, 0, 0, 1)">

import Columns from </span>'./template/columns'<span style="color: rgba(0, 0, 0, 1)">
import Vertical from </span>'./template/vertical'<span style="color: rgba(0, 0, 0, 1)">
import Transverse from </span>'./template/transverse'

<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Layout() {
    const { config: { skin, layout } } </span>=<span style="color: rgba(0, 0, 0, 1)"> appStore()

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 布局模板</span>
    const LayoutComponent = useMemo(() =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">switch</span><span style="color: rgba(0, 0, 0, 1)">(layout) {
            </span><span style="color: rgba(0, 0, 255, 1)">case</span> 'columns'<span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Columns
            </span><span style="color: rgba(0, 0, 255, 1)">case</span> 'vertical'<span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Vertical
            </span><span style="color: rgba(0, 0, 255, 1)">case</span> 'transverse'<span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Transverse
            </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Columns
      }
    }, )
   
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;div className="radmin__container"&gt;
            &lt;LayoutComponent /&gt;
      &lt;/div&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}

export </span><span style="color: rgba(0, 0, 255, 1)">default</span> Layout</pre>
</div>
<p>主模板Main.jsx动态<strong>Permission鉴权</strong>验证。</p>
<div class="cnblogs_code">
<pre>import './index.scss'<span style="color: rgba(0, 0, 0, 1)">
import { Outlet } from </span>'react-router-dom'<span style="color: rgba(0, 0, 0, 1)">
import RScroll from </span>'@/components/rscroll'<span style="color: rgba(0, 0, 0, 1)">
import Permission from </span>'@/components/Permission'<span style="color: rgba(0, 0, 0, 1)">
import Forbidden from </span>'@/views/error/forbidden'<span style="color: rgba(0, 0, 0, 1)">
import { useRoute } from </span>'@/hooks/useRoutes'<span style="color: rgba(0, 0, 0, 1)">

export </span><span style="color: rgba(0, 0, 255, 1)">default</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Main() {
    const route </span>=<span style="color: rgba(0, 0, 0, 1)"> useRoute()

    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;&gt;
            &lt;RScroll&gt;
                &lt;div className="ra__layout-main__wrapper"&gt;<span style="color: rgba(0, 0, 0, 1)">
                  {</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> 鉴权组件 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">}
                  </span>&lt;<span style="color: rgba(0, 0, 0, 1)">Permission
                        roles</span>={route?.meta?<span style="color: rgba(0, 0, 0, 1)">.roles}
                        content</span>={&lt;Forbidden /&gt;}
                  &gt;
                        &lt;Outlet /&gt;
                  &lt;/Permission&gt;
                &lt;/div&gt;
            &lt;/RScroll&gt;
      &lt;/&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}</span></pre>
</div>
<h3>react-router路由配置</h3>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017090936959-1596601401.png"></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* @title    react-router-dom v6路由配置管理
* @author    andy
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

import { useRoutes, Navigate } from </span>'react-router-dom'<span style="color: rgba(0, 0, 0, 1)">

import Error from </span>'@views/error/404'

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 批量导入modules路由</span>
const modules = import.meta.glob('./modules/*.jsx', { eager: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> })
const patchRoutes </span>= Object.keys(modules).map(key =&gt; modules.<span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)">).flat()

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> useRoutes集中式路由配置</span>
export const routes =<span style="color: rgba(0, 0, 0, 1)"> [
    {
      path: </span>'/'<span style="color: rgba(0, 0, 0, 1)">,
      element: </span>&lt;Navigate to="/home" replace={<span style="color: rgba(0, 0, 255, 1)">true</span>} /&gt;,
<span style="color: rgba(0, 0, 0, 1)">      meta: {
            isWhite: </span><span style="color: rgba(0, 0, 255, 1)">true</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 路由白名单</span>
<span style="color: rgba(0, 0, 0, 1)">      }
    },
    ...patchRoutes,
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 404模块 path="*"不能省略</span>
<span style="color: rgba(0, 0, 0, 1)">    {
      path: </span>'*'<span style="color: rgba(0, 0, 0, 1)">,
      element: </span>&lt;Error /&gt;,
<span style="color: rgba(0, 0, 0, 1)">      meta: {
            isWhite: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
      }
    }
]

const Router </span>= () =&gt;<span style="color: rgba(0, 0, 0, 1)"> useRoutes(routes)

export </span><span style="color: rgba(0, 0, 255, 1)">default</span> Router</pre>
</div>
<p><strong>lazyload.jsx配置</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 延迟加载提示
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

import { Suspense } from </span>'react'<span style="color: rgba(0, 0, 0, 1)">
import { Spin } from </span>'@arco-design/web-react'<span style="color: rgba(0, 0, 0, 1)">
import NprogressLoading from </span>'./nprogress'

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 加载提示</span>
const SpinLoading = () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;<span style="color: rgba(0, 0, 0, 1)">Spin
            tip</span>='loading...'<span style="color: rgba(0, 0, 0, 1)">
            style</span>=<span style="color: rgba(0, 0, 0, 1)">{{
                width: </span>'100%'<span style="color: rgba(0, 0, 0, 1)">
            }}
      </span>/&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 延迟加载</span>
const lazyload = LazyComponent =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> React 16.6 新增了&lt;Suspense&gt;组件,懒加载的模式需要我们给他加上一层 Loading的提示加载组件</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> return &lt;Suspense fallback={&lt;SpinLoading /&gt;}&gt;&lt;LazyComponent /&gt;&lt;/Suspense&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span> &lt;Suspense fallback={&lt;NprogressLoading /&gt;}&gt;&lt;LazyComponent /&gt;&lt;/Suspense&gt;
<span style="color: rgba(0, 0, 0, 1)">}

export </span><span style="color: rgba(0, 0, 255, 1)">default</span> lazyload</pre>
</div>
<p><strong>NProgress.jsx配置</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 加载进度条NProgress
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

import { Component } from </span>'react'<span style="color: rgba(0, 0, 0, 1)">
import NProgress from </span>'nprogress'<span style="color: rgba(0, 0, 0, 1)">
import </span>'nprogress/nprogress.css'<span style="color: rgba(0, 0, 0, 1)">

export </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> class NprogressLoading extends Component {
    constructor(props) {
      super(props)
      NProgress.set(.</span>4<span style="color: rgba(0, 0, 0, 1)">)
      NProgress.start()
    }

    componentDidMount() {
      NProgress.done()
    }

    render() {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> &lt;div /&gt;
<span style="color: rgba(0, 0, 0, 1)">    }
}</span></pre>
</div>
<p><strong>主路由main.jsx配置</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 主路由配置
* @author Hs
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

import { lazy } from </span>'react'<span style="color: rgba(0, 0, 0, 1)">
import {
    IconHome, IconDashboard, IconLink, IconCommand, IconUserGroup, IconLock,
    IconMenu, IconSafe, IconBug, IconHighlight, IconUnorderedList, IconStop
} from </span>'@arco-design/web-react/icon'<span style="color: rgba(0, 0, 0, 1)">
import Layout from </span>'@/layouts'<span style="color: rgba(0, 0, 0, 1)">
import Blank from </span>'@/layouts/blank'<span style="color: rgba(0, 0, 0, 1)">
import lazyload from </span>'../lazyload'<span style="color: rgba(0, 0, 0, 1)">

export </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> [
    </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">首页模块</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    {
      path: </span>'/home'<span style="color: rgba(0, 0, 0, 1)">,
      key: </span>'/home', <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 用于Menu组件跳转路由地址</span>
      element: &lt;Layout /&gt;,
<span style="color: rgba(0, 0, 0, 1)">      meta: {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> icon: 've-icon-home', // 菜单图标</span>
            icon: &lt;IconHome /&gt;,
            name: 'layout__main-menu__home', <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> i18n国际化标题</span>
            title: '主页'<span style="color: rgba(0, 0, 0, 1)">,
            isAuth: </span><span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 需要鉴权</span>
            isHidden: <span style="color: rgba(0, 0, 255, 1)">false</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 是否隐藏菜单</span>
            isAffix: <span style="color: rgba(0, 0, 255, 1)">true</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 固定tabview标签栏(不可关闭)</span>
<span style="color: rgba(0, 0, 0, 1)">      },
      children: [
            {
                key: </span>'/home'<span style="color: rgba(0, 0, 0, 1)">,
                index: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                element: lazyload(lazy(() </span>=&gt; import('@views/home'<span style="color: rgba(0, 0, 0, 1)">))),
                meta: {
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> icon: 've-icon-home',</span>
                  icon: &lt;IconHome /&gt;,
                  name: 'layout__main-menu__home-index'<span style="color: rgba(0, 0, 0, 1)">,
                  title: </span>'首页'<span style="color: rgba(0, 0, 0, 1)">,
                  isAuth: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
                }
            },
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 工作台</span>
<span style="color: rgba(0, 0, 0, 1)">            {
                path: </span>'dashboard'<span style="color: rgba(0, 0, 0, 1)">,
                key: </span>'/home/dashboard'<span style="color: rgba(0, 0, 0, 1)">,
                element: lazyload(lazy(() </span>=&gt; import('@views/home/dashboard'<span style="color: rgba(0, 0, 0, 1)">))),
                meta: {
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> icon: 've-icon-computer',</span>
                  icon: &lt;IconDashboard /&gt;,
                  name: 'layout__main-menu__home-workplace'<span style="color: rgba(0, 0, 0, 1)">,
                  title: </span>'工作台'<span style="color: rgba(0, 0, 0, 1)">,
                  isAuth: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
                }
            },
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 外部链接</span>
<span style="color: rgba(0, 0, 0, 1)">            {
                path: </span>'https://react.dev/'<span style="color: rgba(0, 0, 0, 1)">,
                key: </span>'https://react.dev/'<span style="color: rgba(0, 0, 0, 1)">,
                meta: {
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> icon: 've-icon-clip',</span>
                  icon: &lt;IconLink /&gt;,
                  name: 'layout__main-menu__home-apidocs'<span style="color: rgba(0, 0, 0, 1)">,
                  title: </span>'react.js官方文档'<span style="color: rgba(0, 0, 0, 1)">,
                  rootRoute: </span>'/home'<span style="color: rgba(0, 0, 0, 1)">
                }
            }
      ]
    },

    </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">组件模块</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    {
      ...
    },

    </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">用户管理模块</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    {
      ...
    },

    </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">权限模块</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    {
      ...
    },

    </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">错误模块</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    {
      ...
    }
]</span></pre>
</div>
<p><strong><span style="font-size: 16px; font-family: &quot;Microsoft YaHei&quot;"><em><span style="color: rgba(255, 0, 0, 1)">备注:路由菜单参数配置说明。</span></em></span></strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* @description 路由参数说明
* @param path ==&gt; 路由地址标识
* @param key ==&gt; 用于Menu组件跳转路由地址
* @param redirect ==&gt; 重定向地址
* @param element ==&gt; 视图页面路径
* 菜单信息(meta)
*         @param meta.icon ==&gt; 菜单图标
*         @param meta.title ==&gt; 菜单标题
*         @param meta.name ==&gt; i18n国际化标题
*         @param meta.roles ==&gt; 页面权限 ['admin', 'dev', 'test']
*         @param meta.isAuth ==&gt; 是否需要验证
*         @param meta.isHidden ==&gt; 是否隐藏页面
*         @param meta.isAffix ==&gt; 是否固定标签(tabs标签栏不能关闭)
* </span><span style="color: rgba(0, 128, 0, 1)">*/</span></pre>
</div>
<h3>react自定义路由菜单Menu</h3>
<p>基于arco.design组件库提供的Menu组件封装三种不同的路由菜单。</p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017085724006-761176492.png">&nbsp;&nbsp;<img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017085837809-142280797.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017090103836-614971786.png"></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">RouteMenu </span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">RouteMenu </span><span style="color: rgba(255, 0, 0, 1)">rootRouteEnable </span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">RouteMenu </span><span style="color: rgba(255, 0, 0, 1)">rootRouteEnable mode</span><span style="color: rgba(0, 0, 255, 1)">="horizontal"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span></pre>
</div>
<p><strong>RouteMenu路由菜单模板</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">/**
* 路由菜单模板
*/

import './index.scss'
import { useState, useMemo, useEffect } from 'react'
import { useNavigate, useLocation } from 'react-router-dom'
import { Menu } from '@arco-design/web-react'
import Icon from '@components/Icon'
import RouteSubMenu from './submenu'
import { routes } from '@/routers'
import { getCurrentRootRoute, findParentRoute } from '@/hooks/useRoutes'
import Locales from '@/locales'

export default function RouteMenu(props) {
    const {
      // 菜单类型(垂直vertical 水平菜单horizontal 弹出pop)
      mode = 'vertical',
      // 菜单风格('light' | 'dark')
      theme = 'light',
      // 是否开启一级路由菜单
      rootRouteEnable = false,

      style = {}
    } = props

    const navigate = useNavigate()
    const { pathname } = useLocation()
    const t = Locales()
    const = useState([])
    const rootRoute = getCurrentRootRoute()
    const filterRoutes = routes.filter(item =&gt; !item?.meta?.isWhite)

    const menuRoutes = useMemo(() =&gt; {
      if(rootRouteEnable) {
            return filterRoutes
      }
      // 过滤一级菜单
      return filterRoutes.find(item =&gt; item.path == rootRoute &amp;&amp; item.children)?.children
    }, )

    useEffect(() =&gt; {
      setOpenKeys(getKeys(pathname))
    }, )

    // 获取选中菜单路由keys数组
    const getKeys = (key) =&gt; {
      return findParentRoute(menuRoutes, key)?.map(item =&gt; item?.key)
    }

    const handleNavigate = (key) =&gt; {
      const reg = /[-a-zA-Z0-9]{0,62}(\.[-a-zA-Z0-9]{0,62})+\.?/
      if(reg.test(key)) {
            window.open(key)
      }else {
            navigate(key)
      }
    }

    return (
      </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Menu
            </span><span style="color: rgba(255, 0, 0, 1)">className</span><span style="color: rgba(0, 0, 255, 1)">="ra__menus"</span><span style="color: rgba(255, 0, 0, 1)">
            mode</span><span style="color: rgba(0, 0, 255, 1)">={mode}
            </span><span style="color: rgba(255, 0, 0, 1)">theme</span><span style="color: rgba(0, 0, 255, 1)">={theme}
            </span><span style="color: rgba(255, 0, 0, 1)">selectedKeys</span><span style="color: rgba(0, 0, 255, 1)">={}
            </span><span style="color: rgba(255, 0, 0, 1)">openKeys</span><span style="color: rgba(0, 0, 255, 1)">={openKeys}
            </span><span style="color: rgba(255, 0, 0, 1)">levelIndent</span><span style="color: rgba(0, 0, 255, 1)">={28}
            </span><span style="color: rgba(255, 0, 0, 1)">style</span><span style="color: rgba(0, 0, 255, 1)">={{ </span><span style="color: rgba(255, 0, 0, 1)">...style }}
            onClickMenuItem</span><span style="color: rgba(0, 0, 255, 1)">={handleNavigate}
            </span><span style="color: rgba(255, 0, 0, 1)">onClickSubMenu</span><span style="color: rgba(0, 0, 255, 1)">={(_, </span><span style="color: rgba(255, 0, 0, 1)">openKeys) </span><span style="color: rgba(0, 0, 255, 1)">=</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)"> {
                setOpenKeys(openKeys)
            }}
      &gt;
            { menuRoutes.map(item =&gt; {
                if(item?.children) {
                  return RouteSubMenu(item, t)
                }
                return (
                  !item?.meta?.isHidden &amp;&amp;
                  </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(255, 0, 0, 1)">.Item className</span><span style="color: rgba(0, 0, 255, 1)">="ra__menuItem"</span><span style="color: rgba(255, 0, 0, 1)"> key</span><span style="color: rgba(0, 0, 255, 1)">={item.redirect </span><span style="color: rgba(255, 0, 0, 1)">|| item.key}</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
                        { item?.meta?.icon &amp;&amp; </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Icon </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">={item.meta.icon} </span><span style="color: rgba(255, 0, 0, 1)">size</span><span style="color: rgba(0, 0, 255, 1)">={18} </span><span style="color: rgba(255, 0, 0, 1)">style</span><span style="color: rgba(0, 0, 255, 1)">={{marginRight: </span><span style="color: rgba(255, 0, 0, 1)">10}} </span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span><span style="color: rgba(0, 0, 0, 1)"> }
                        { item?.meta?.name &amp;&amp; </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">span</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{t}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">span</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)"> }
                  </span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu.Item</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
                )
            })}
      </span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
    )
}</span></pre>
</div>
<h3>react18状态管理zustand</h3>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017093057983-1460989159.png"></p>
<p><em><strong>Zustand</strong></em>新一代react状态管理工具,内置多种插件,支持<strong>persist</strong>本地存储服务。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* react18状态管理库Zustand4,中间件persist本地持久化存储
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
import { create } from </span>'zustand'<span style="color: rgba(0, 0, 0, 1)">
import { persist, createJSONStorage } from </span>'zustand/middleware'<span style="color: rgba(0, 0, 0, 1)">
import { generate, getRgbStr } from </span>'@arco-design/color'<span style="color: rgba(0, 0, 0, 1)">

export const appStore </span>=<span style="color: rgba(0, 0, 0, 1)"> create(
    persist(
      (set, get) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> ({
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 语言(中文zh-CN 英文en 繁体字zh-TW)</span>
            lang: 'zh-CN'<span style="color: rgba(0, 0, 0, 1)">,
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 角色类型 roles: ['admin'] / roles: ['admin', 'dev'] / roles: ['dev', test']</span>
            roles: ["dev"<span style="color: rgba(0, 0, 0, 1)">],
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 配置信息</span>
<span style="color: rgba(0, 0, 0, 1)">            config: {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 布局(分栏columns 纵向vertical 横向transverse)</span>
                layout: 'columns'<span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 模式(亮色light - 暗黑dark)</span>
                mode: 'light'<span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 主题色</span>
                theme: '#3491FA'<span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 是否折叠菜单</span>
                collapsed: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 开启面包屑导航</span>
                breadcrumb: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 开启标签栏</span>
                tabsview: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                tabRoutes: [],
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 显示搜索</span>
                showSearch: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 显示全屏</span>
                showFullscreen: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 显示语言</span>
                showLang: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 显示公告</span>
                showNotice: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 显示底部</span>
                showFooter: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
            },
            
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 更新配置</span>
            updateConfig: (key, value) =&gt;<span style="color: rgba(0, 0, 0, 1)"> set({
                config: { ...get().config, : value }
            }),
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置角色</span>
            setRoles: (roles) =&gt;<span style="color: rgba(0, 0, 0, 1)"> set({roles}),
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置多语言</span>
            setLang: (lang) =&gt;<span style="color: rgba(0, 0, 0, 1)"> set({lang}),
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置主题模式</span>
            setMode: (mode) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 0, 255, 1)">if</span>(mode == 'dark'<span style="color: rgba(0, 0, 0, 1)">) {
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置为暗黑主题</span>
                  document.body.setAttribute('arco-theme', 'dark'<span style="color: rgba(0, 0, 0, 1)">)
                }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 恢复亮色主题</span>
                  document.body.removeAttribute('arco-theme'<span style="color: rgba(0, 0, 0, 1)">)
                }
                get().updateConfig(</span>'mode'<span style="color: rgba(0, 0, 0, 1)">, mode)
            },
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置主题样式</span>
            setTheme: (theme) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
                const colors </span>= generate(theme, { list: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> })
                colors.map((item, index) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
                  const rgbStr </span>=<span style="color: rgba(0, 0, 0, 1)"> getRgbStr(item)
                  document.body.style.setProperty(`</span>--arcoblue-${index + 1<span style="color: rgba(0, 0, 0, 1)">}`, rgbStr)
                })
                get().updateConfig(</span>'theme'<span style="color: rgba(0, 0, 0, 1)">, theme)
            }
      }),
      {
            name: </span>'appState'<span style="color: rgba(0, 0, 0, 1)">,
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> name: 'app-store', // name of the item in the storage (must be unique)</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> storage: createJSONStorage(() =&gt; sessionStorage), // by default, 'localStorage'</span>
<span style="color: rgba(0, 0, 0, 1)">      }
    )
)</span></pre>
</div>
<h3>react18国际化配置i18n</h3>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017093750196-2139331344.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017093850844-390073734.png"></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 国际化配置
* @author YXY
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

import { appStore } from </span>'@/store/app'

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 引入语言配置</span>
import enUS from './en-US'<span style="color: rgba(0, 0, 0, 1)">
import zhCN from </span>'./zh-CN'<span style="color: rgba(0, 0, 0, 1)">
import zhTW from </span>'./zh-TW'<span style="color: rgba(0, 0, 0, 1)">

export const locales </span>=<span style="color: rgba(0, 0, 0, 1)"> {
    </span>'en'<span style="color: rgba(0, 0, 0, 1)">: enUS,
    </span>'zh-CN'<span style="color: rgba(0, 0, 0, 1)">: zhCN,
    </span>'zh-TW'<span style="color: rgba(0, 0, 0, 1)">: zhTW
}

export </span><span style="color: rgba(0, 0, 255, 1)">default</span> (locale) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    const appState </span>=<span style="color: rgba(0, 0, 0, 1)"> appStore()
    const lang </span>= appState.lang || 'zh-CN'

    <span style="color: rgba(0, 0, 255, 1)">return</span> (locale || locales) ||<span style="color: rgba(0, 0, 0, 1)"> {}
}</span></pre>
</div>
<p>App.jsx引入arco.design组件库语言包。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 入口模板
* @author Hs
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

import { useEffect, useMemo } from </span>'react'<span style="color: rgba(0, 0, 0, 1)">
import { HashRouter } from </span>'react-router-dom'
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 通过 ConfigProvider 组件实现国际化</span>
import { ConfigProvider } from '@arco-design/web-react'
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 引入语言包</span>
import enUS from '@arco-design/web-react/es/locale/en-US'<span style="color: rgba(0, 0, 0, 1)">
import zhCN from </span>'@arco-design/web-react/es/locale/zh-CN'<span style="color: rgba(0, 0, 0, 1)">
import zhTW from </span>'@arco-design/web-react/es/locale/zh-TW'<span style="color: rgba(0, 0, 0, 1)">

import { AuthRouter } from </span>'@/hooks/useRoutes'<span style="color: rgba(0, 0, 0, 1)">
import { appStore } from </span>'@/store/app'

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 引入路由配置</span>
import Router from './routers'

<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> App() {
    const { lang, config: { mode, theme }, setMode, setTheme } </span>=<span style="color: rgba(0, 0, 0, 1)"> appStore()

    const locale </span>= useMemo(() =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">switch</span><span style="color: rgba(0, 0, 0, 1)">(lang) {
            </span><span style="color: rgba(0, 0, 255, 1)">case</span> 'en'<span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> enUS
            </span><span style="color: rgba(0, 0, 255, 1)">case</span> 'zh-CN'<span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> zhCN
            </span><span style="color: rgba(0, 0, 255, 1)">case</span> 'zh-TW'<span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> zhTW
            </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> zhCN
      }
    }, )

    useEffect(() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      setMode(mode)
      setTheme(theme)
    }, [])

    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;ConfigProvider locale={locale}&gt;
            &lt;HashRouter&gt;
                &lt;AuthRouter&gt;
                  &lt;Router /&gt;
                &lt;/AuthRouter&gt;
            &lt;/HashRouter&gt;
      &lt;/ConfigProvider&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}

export </span><span style="color: rgba(0, 0, 255, 1)">default</span> App</pre>
</div>
<p><strong>Lang.jsx配置</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">import { Dropdown, Menu, Button } from '@arco-design/web-react'
import Icon from '@components/Icon'
import { appStore } from '@/store/app'

export default function Lang() {
    const { lang, setLang } = appStore()

    const handleLang = val =&gt; {
      setLang(val)
    }

    return (
      </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Dropdown
            </span><span style="color: rgba(255, 0, 0, 1)">position</span><span style="color: rgba(0, 0, 255, 1)">="bottom"</span><span style="color: rgba(255, 0, 0, 1)">
            droplist</span><span style="color: rgba(0, 0, 255, 1)">={
                </span><span style="color: rgba(255, 0, 0, 1)">&lt;Menu className</span><span style="color: rgba(0, 0, 255, 1)">="radmin__dropdownLang"</span><span style="color: rgba(255, 0, 0, 1)"> defaultSelectedKeys</span><span style="color: rgba(0, 0, 255, 1)">={} </span><span style="color: rgba(255, 0, 0, 1)">onClickMenuItem</span><span style="color: rgba(0, 0, 255, 1)">={handleLang}</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
                  <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(255, 0, 0, 1)">.Item key</span><span style="color: rgba(0, 0, 255, 1)">='zh-CN'</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>简体中文 <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">span</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>zh-CN<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">span</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu.Item</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
                  <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(255, 0, 0, 1)">.Item key</span><span style="color: rgba(0, 0, 255, 1)">="zh-TW"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>繁体字 <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">span</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>zh-TW<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">span</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu.Item</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
                  <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(255, 0, 0, 1)">.Item key</span><span style="color: rgba(0, 0, 255, 1)">="en"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>英文 <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">span</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>en<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">span</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu.Item</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
                <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
            }
      &gt;
            </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Button
                </span><span style="color: rgba(255, 0, 0, 1)">shape</span><span style="color: rgba(0, 0, 255, 1)">="circle"</span><span style="color: rgba(255, 0, 0, 1)">
                size</span><span style="color: rgba(0, 0, 255, 1)">="small"</span><span style="color: rgba(255, 0, 0, 1)">
                icon</span><span style="color: rgba(0, 0, 255, 1)">={&lt;Icon </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="ve-icon-lang"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span><span style="color: rgba(0, 0, 0, 1)">}
            /&gt;
      </span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Dropdown</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
    )
}</span></pre>
</div>
<h3>Tabs.jsx动态路由栏</h3>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017094809954-295333064.png"></p>
<p>项目中动态路由栏tabs采用arco.design组件库Tabs组件自定义实现功能。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Tabs
    </span><span style="color: rgba(255, 0, 0, 1)">activeTab</span><span style="color: rgba(0, 0, 255, 1)">={pathname}
    </span><span style="color: rgba(255, 0, 0, 1)">editable
    showAddButton</span><span style="color: rgba(0, 0, 255, 1)">={false}
    </span><span style="color: rgba(255, 0, 0, 1)">onDeleteTab</span><span style="color: rgba(0, 0, 255, 1)">={key =</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)"> delTabs(key)}
&gt;
    { tabRoutes.map(item =&gt; (
      </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Tabs</span><span style="color: rgba(255, 0, 0, 1)">.TabPane
            closable</span><span style="color: rgba(0, 0, 255, 1)">={!item?.meta?.isAffix}
            </span><span style="color: rgba(255, 0, 0, 1)">key</span><span style="color: rgba(0, 0, 255, 1)">={item?.redirect </span><span style="color: rgba(255, 0, 0, 1)">|| item?.key}
            title</span><span style="color: rgba(0, 0, 255, 1)">={
                </span><span style="color: rgba(255, 0, 0, 1)">&lt;Dropdown
                  trigger</span><span style="color: rgba(0, 0, 255, 1)">='contextMenu'
                  </span><span style="color: rgba(255, 0, 0, 1)">position</span><span style="color: rgba(0, 0, 255, 1)">='bl'
                  </span><span style="color: rgba(255, 0, 0, 1)">droplist</span><span style="color: rgba(0, 0, 255, 1)">={
                        </span><span style="color: rgba(255, 0, 0, 1)">&lt;Menu className</span><span style="color: rgba(0, 0, 255, 1)">="ra__dropdownContext"</span><span style="color: rgba(255, 0, 0, 1)"> onClickMenuItem</span><span style="color: rgba(0, 0, 255, 1)">={(key, </span><span style="color: rgba(255, 0, 0, 1)">e) </span><span style="color: rgba(0, 0, 255, 1)">=</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)"> handleClickMenuItem(key, e, item)}&gt;
                            </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(255, 0, 0, 1)">.Item key</span><span style="color: rgba(0, 0, 255, 1)">="close"</span><span style="color: rgba(255, 0, 0, 1)"> disabled</span><span style="color: rgba(0, 0, 255, 1)">={item?.meta?.isAffix}</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;</span><span style="color: rgba(128, 0, 0, 1)">Icon </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="ve-icon-close"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>{t['tabview__contextmenu-close']}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu.Item</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
                            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(255, 0, 0, 1)">.Item key</span><span style="color: rgba(0, 0, 255, 1)">="closeLeft"</span><span style="color: rgba(255, 0, 0, 1)"> disabled</span><span style="color: rgba(0, 0, 255, 1)">={isFirstTab()}</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;</span><span style="color: rgba(128, 0, 0, 1)">Icon </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="ve-icon-prev"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>{t['tabview__contextmenu-closeleft']}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu.Item</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
                            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(255, 0, 0, 1)">.Item key</span><span style="color: rgba(0, 0, 255, 1)">="closeRight"</span><span style="color: rgba(255, 0, 0, 1)"> disabled</span><span style="color: rgba(0, 0, 255, 1)">={isLastTab()}</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;</span><span style="color: rgba(128, 0, 0, 1)">Icon </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="ve-icon-next"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>{t['tabview__contextmenu-closeright']}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu.Item</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
                            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(255, 0, 0, 1)">.Item key</span><span style="color: rgba(0, 0, 255, 1)">="closeOther"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;</span><span style="color: rgba(128, 0, 0, 1)">Icon </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="ve-icon-reset"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>{t['tabview__contextmenu-closeother']}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu.Item</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
                            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(255, 0, 0, 1)">.Item key</span><span style="color: rgba(0, 0, 255, 1)">="closeAll"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;</span><span style="color: rgba(128, 0, 0, 1)">Icon </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="ve-icon-close-circle-o"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>{t['tabview__contextmenu-closeall']}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu.Item</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
                        <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Menu</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
                  }
                  onVisibleChange={visible=&gt;handleOpenContextMenu(visible, item)}
                &gt;
                  </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">span </span><span style="color: rgba(255, 0, 0, 1)">className</span><span style="color: rgba(0, 0, 255, 1)">="ra__tabsview-title"</span><span style="color: rgba(255, 0, 0, 1)"> onClick</span><span style="color: rgba(0, 0, 255, 1)">={() =</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)"> navigate(item?.redirect || item?.key)}&gt;
                        </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">TabIcon </span><span style="color: rgba(255, 0, 0, 1)">path</span><span style="color: rgba(0, 0, 255, 1)">={item?.key} </span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span><span style="color: rgba(0, 0, 0, 1)">
                        { t }
                  </span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">span</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
                <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Dropdown</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
            }
      /&gt;
    ))}
</span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Tabs</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<div class="cnblogs_code">
<pre>export <span style="color: rgba(0, 0, 255, 1)">default</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> TabsView() {
    const { pathname } </span>=<span style="color: rgba(0, 0, 0, 1)"> useLocation()
    const navigate </span>=<span style="color: rgba(0, 0, 0, 1)"> useNavigate()
    const </span>=<span style="color: rgba(0, 0, 0, 1)"> useState()
    const { config: { tabRoutes }, updateConfig } </span>=<span style="color: rgba(0, 0, 0, 1)"> appStore()
    const route </span>=<span style="color: rgba(0, 0, 0, 1)"> useRoute()
    const t </span>=<span style="color: rgba(0, 0, 0, 1)"> Locales()

    useEffect(() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      addTabs()
    }, )

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 添加</span>
    const addTabs = () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      const tabIndex </span>= tabRoutes.findIndex(item =&gt; item?.key ===<span style="color: rgba(0, 0, 0, 1)"> pathname)
      let newTabs </span>=<span style="color: rgba(0, 0, 0, 1)"> tabRoutes
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(tabIndex == -1<span style="color: rgba(0, 0, 0, 1)">) {
            newTabs.push(route)
      }
      newTabs.map(item </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
            item.isActive </span>= <span style="color: rgba(0, 0, 255, 1)">false</span>
            <span style="color: rgba(0, 0, 255, 1)">if</span>(item?.key ===<span style="color: rgba(0, 0, 0, 1)"> pathname) {
                item.isActive </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
            }
      })
      updateConfig(</span>'tabRoutes'<span style="color: rgba(0, 0, 0, 1)">, newTabs)
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 删除</span>
    const delTabs = (path) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      const tabIndex </span>= tabRoutes.findIndex(item =&gt; item?.key ===<span style="color: rgba(0, 0, 0, 1)"> path)
      let newTabs </span>=<span style="color: rgba(0, 0, 0, 1)"> tabRoutes
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(tabIndex &gt; -1<span style="color: rgba(0, 0, 0, 1)">) {
            newTabs.splice(tabIndex, </span>1<span style="color: rgba(0, 0, 0, 1)">)
            updateConfig(</span>'tabRoutes'<span style="color: rgba(0, 0, 0, 1)">, newTabs)
            updateTabs(newTabs)
      }
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 删除左侧标签</span>
    const delLeftTabs = (path) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      const tabIndex </span>= tabRoutes.findIndex(item =&gt; item?.key ===<span style="color: rgba(0, 0, 0, 1)"> path)
      let newTabs </span>=<span style="color: rgba(0, 0, 0, 1)"> tabRoutes
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(tabIndex &gt; -1<span style="color: rgba(0, 0, 0, 1)">) {
            newTabs </span>= newTabs.filter((item, i) =&gt; item?.meta?.isAffix || i &gt;=<span style="color: rgba(0, 0, 0, 1)"> tabIndex)
            updateConfig(</span>'tabRoutes'<span style="color: rgba(0, 0, 0, 1)">, newTabs)
            updateTabs(newTabs)
      }
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 删除右侧标签</span>
    const delRightTabs = (path) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      const tabIndex </span>= tabRoutes.findIndex(item =&gt; item?.key ===<span style="color: rgba(0, 0, 0, 1)"> path)
      let newTabs </span>=<span style="color: rgba(0, 0, 0, 1)"> tabRoutes
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(tabIndex &gt; -1<span style="color: rgba(0, 0, 0, 1)">) {
            newTabs </span>= newTabs.filter((item, i) =&gt; item?.meta?.isAffix || i &lt;=<span style="color: rgba(0, 0, 0, 1)"> tabIndex)
            updateConfig(</span>'tabRoutes'<span style="color: rgba(0, 0, 0, 1)">, newTabs)
            updateTabs(newTabs)
      }
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 删除其它</span>
    const delOtherTabs = (path) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      let newTabs </span>= tabRoutes.filter(item =&gt; item?.meta?.isAffix || item?.key ===<span style="color: rgba(0, 0, 0, 1)"> path)
      updateConfig(</span>'tabRoutes'<span style="color: rgba(0, 0, 0, 1)">, newTabs)
      updateTabs(newTabs)
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 删除所有</span>
    const delAllTabs = () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      let newTabs </span>= tabRoutes.filter(item =&gt; item?.meta?<span style="color: rgba(0, 0, 0, 1)">.isAffix)
      updateConfig(</span>'tabRoutes'<span style="color: rgba(0, 0, 0, 1)">, newTabs)
      updateTabs(newTabs)
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 更新跳转选项卡</span>
    const updateTabs = (tabs) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      const nextTab </span>= tabs || tabs
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(!nextTab) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">
      navigate(nextTab</span>?.redirect || nextTab?<span style="color: rgba(0, 0, 0, 1)">.key)
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 是否第一个标签</span>
    const isFirstTab = () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> selectedTab?.key === tabRoutes?.key || selectedTab?.key === '/home'<span style="color: rgba(0, 0, 0, 1)">
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 是否最后一个标签</span>
    const isLastTab = () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> selectedTab?.key === tabRoutes?<span style="color: rgba(0, 0, 0, 1)">.key
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 打开右键菜单</span>
    const handleOpenContextMenu = (visible, item) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(visible) {
            setSelectedTab(item)
      }
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 点击右键菜单项</span>
    const handleClickMenuItem = (key, e, item) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      e.stopPropagation()
      const path </span>= item?<span style="color: rgba(0, 0, 0, 1)">.key
      </span><span style="color: rgba(0, 0, 255, 1)">switch</span><span style="color: rgba(0, 0, 0, 1)">(key) {
            </span><span style="color: rgba(0, 0, 255, 1)">case</span> 'close'<span style="color: rgba(0, 0, 0, 1)">:
                delTabs(path)
                </span><span style="color: rgba(0, 0, 255, 1)">break</span>
            <span style="color: rgba(0, 0, 255, 1)">case</span> 'closeLeft'<span style="color: rgba(0, 0, 0, 1)">:
                delLeftTabs(path)
                </span><span style="color: rgba(0, 0, 255, 1)">break</span>
            <span style="color: rgba(0, 0, 255, 1)">case</span> 'closeRight'<span style="color: rgba(0, 0, 0, 1)">:
                delRightTabs(path)
                </span><span style="color: rgba(0, 0, 255, 1)">break</span>
            <span style="color: rgba(0, 0, 255, 1)">case</span> 'closeOther'<span style="color: rgba(0, 0, 0, 1)">:
                delOtherTabs(path)
                </span><span style="color: rgba(0, 0, 255, 1)">break</span>
            <span style="color: rgba(0, 0, 255, 1)">case</span> 'closeAll'<span style="color: rgba(0, 0, 0, 1)">:
                delAllTabs()
                </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      ...
    )
}</span></pre>
</div>
<p>OK,以上就是react18+arco开发后台系统的一些分享,希望对大家有所帮助~&nbsp;💖</p>
<p><strong>最后附上两个最新项目实例</strong></p>
<p><span style="font-size: 12px">https://www.cnblogs.com/xiaoyan2017/p/17630296.html</span></p>
<p><span style="font-size: 12px">https://www.cnblogs.com/xiaoyan2017/p/17468074.html</span></p>
<p><img src="https://img2023.cnblogs.com/blog/1289798/202310/1289798-20231017100003691-537573191.gif"></p>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    本文为博主原创文章,未经博主允许不得转载,欢迎大家一起交流 QQ(282310962) wx(xy190310)<br><br>
来源:https://www.cnblogs.com/xiaoyan2017/p/17769058.html
頁: [1]
查看完整版本: React-Admin后台管理模板|react18+arco+zustand后台解决方案