react-arco-admin:基于vite4+react18+arco-design+zustand4
搭建后台管理系统模板。
react18-admin 支持暗夜+亮色主题模式。
react18-admin支持自定义主题配色、分栏+水平+垂直布局样式。
使用技术
- 编辑器:vscode
- 框架技术:react18+vite4+react-router-dom+zustand4+mockjs
- 组件库:ArcoDesign (字节跳动react组件库)
- 路由插件:react-router-dom^6.16.0
- 状态管理:zustand^4.4.1
- 模拟数据:mockjs^1.1.0
- 模拟请求:axios^1.5.1
- 图表库:bizcharts^4.1.22
- 编辑器组件:@wangeditor/editor-for-react^1.0.6
- markdown编辑器:@uiw/react-md-editor^3.23.6
- 请求进度插件:nprogress^0.2.0
项目结构
使用vite4
构建工具创建react18项目,遵循react18 hooks
编码方式。
App.jsx模板
/**
* 入口模板
* @author Hs
*/
import { useEffect, useMemo } from 'react'
import { HashRouter } from 'react-router-dom'
// 通过 ConfigProvider 组件实现国际化
import { ConfigProvider } from '@arco-design/web-react'
// 引入语言包
import enUS from '@arco-design/web-react/es/locale/en-US'
import zhCN from '@arco-design/web-react/es/locale/zh-CN'
import zhTW from '@arco-design/web-react/es/locale/zh-TW'
import { AuthRouter } from '@/hooks/useRoutes'
import { appStore } from '@/store/app'
// 引入路由配置
import Router from './routers'
function App() {
const { lang, config: { mode, theme }, setMode, setTheme } = appStore()
const locale = useMemo(() => {
switch(lang) {
case 'en':
return enUS
case 'zh-CN':
return zhCN
case 'zh-TW':
return zhTW
default:
return zhCN
}
}, [lang])
useEffect(() => {
setMode(mode)
setTheme(theme)
}, [])
return (
<ConfigProvider locale={locale}>
<HashRouter>
<AuthRouter>
<Router />
</AuthRouter>
</HashRouter>
</ConfigProvider>
)
}
export default App
公共模板布局
支持分栏+水平+垂直布局样式。
/**
* Layout布局模板
* @author YXY
*/
import { useMemo } from 'react'
import { appStore } from '@/store/app'
import Columns from './template/columns'
import Vertical from './template/vertical'
import Transverse from './template/transverse'
function Layout() {
const { config: { skin, layout } } = appStore()
// 布局模板
const LayoutComponent = useMemo(() => {
switch(layout) {
case 'columns':
return Columns
case 'vertical':
return Vertical
case 'transverse':
return Transverse
default:
return Columns
}
}, [layout])
return (
<div className="radmin__container">
<LayoutComponent />
</div>
)
}
export default Layout
路由管理react-router配置
/**
* @title react-router v6路由配置
* @author Hs Q:282310962
*/
import { useRoutes, Navigate } from 'react-router-dom'
import Error from '@views/error/404'
// 批量导入modules路由
const modules = import.meta.glob('./modules/*.jsx', { eager: true })
const patchRoutes = Object.keys(modules).map(key => modules[key].default).flat()
// useRoutes集中式路由配置
export const routes = [
{
path: '/',
element: <Navigate to="/home" replace={true} />,
meta: {
isWhite: true // 路由白名单
}
},
...patchRoutes,
// 404模块 path="*"不能省略
{
path: '*',
element: <Error />,
meta: {
isWhite: true
}
}
]
const Router = () => useRoutes(routes)
export default Router
路由配置参数如下:
/**
* @description 路由参数说明
* @param path ==> 路由地址标识
* @param key ==> 用于Menu组件跳转路由地址
* @param redirect ==> 重定向地址
* @param element ==> 视图页面路径
* 菜单信息(meta)
* @param meta.icon ==> 菜单图标
* @param meta.title ==> 菜单标题
* @param meta.name ==> i18n国际化标题
* @param meta.roles ==> 页面权限 ['admin', 'dev', 'test']
* @param meta.isAuth ==> 是否需要验证
* @param meta.isHidden ==> 是否隐藏页面
* @param meta.isAffix ==> 是否固定标签(tabs标签栏不能关闭)
* */
路由菜单模板
如上图:在分栏/垂直/水平布局模板中,使用不同的路由菜单。
/**
* 路由菜单模板
*/
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 [openKeys, setOpenKeys] = useState([])
const rootRoute = getCurrentRootRoute()
const filterRoutes = routes.filter(item => !item?.meta?.isWhite)
const menuRoutes = useMemo(() => {
if(rootRouteEnable) {
return filterRoutes
}
// 过滤一级菜单
return filterRoutes.find(item => item.path == rootRoute && item.children)?.children
}, [pathname])
useEffect(() => {
setOpenKeys(getKeys(pathname))
}, [pathname])
// 获取选中菜单路由keys数组
const getKeys = (key) => {
return findParentRoute(menuRoutes, key)?.map(item => item?.key)
}
const handleNavigate = (key) => {
const reg = /[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/
if(reg.test(key)) {
window.open(key)
}else {
navigate(key)
}
}
return (
<Menu
className="ra__menus"
mode={mode}
theme={theme}
selectedKeys={[pathname]}
openKeys={openKeys}
levelIndent={28}
style={{ ...style }}
onClickMenuItem={handleNavigate}
onClickSubMenu={(_, openKeys) => {
setOpenKeys(openKeys)
}}
>
{ menuRoutes.map(item => {
if(item?.children) {
return RouteSubMenu(item, t)
}
return (
!item?.meta?.isHidden &&
<Menu.Item className="ra__menuItem" key={item.redirect || item.key}>
{ item?.meta?.icon && <Icon name={item.meta.icon} size={18} style={{marginRight: 10}} /> }
{ item?.meta?.name && <span>{t[item.meta.name]}</span> }
</Menu.Item>
)
})}
</Menu>
)
}
https://juejin.cn/post/7290800838623789112
Okr,以上就是react18 hooks+arcoDesign开发管理后台的一些实战分享。