# React 管理系统
**Repository Path**: hepingkang/react-management-system
## Basic Information
- **Project Name**: React 管理系统
- **Description**: 基于 react 18 、ts、react-router-dom 6、 ant-design、vite 开发的通用模板
- **Primary Language**: JavaScript
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 2
- **Created**: 2022-11-18
- **Last Updated**: 2023-07-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: React, TypeScript, Redux, Ant-Design
## README
## 一、配置项目路径别名
#### 1. 路径别名
1. 需要手动配置 @ 符号的指向
2. 在 vite.config.ts 中添加配置
```js
import path from 'path';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
// dirname 目录名
'@': path.resolve(__dirname, './src')
}
}
})
```
## 二、路由配置(组件写法)
#### 1. 展示
```js
// router 文件夹下的 index
import App from '../App'
import Home from '../views/Home'
import About from '../views/About'
// BrowserRouter history 模式 (/home)
// HashRouter hash 模式 (#home)
import { BrowserRouter, Routes, Route } from 'react-router-dom'
const baserRouter = () => (
// 一个 route 就是一个路由
// path 路由路径
// element 路由路径对应的组件
}>
// 子组件,所有组件都渲染在 app 组件中
} />
} />
)
// 导出配置好的路由组件
export default baserRouter
// main
// 导入路由组件
import BaserRouter from './router'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
// 渲染
,
)
// app
import { Outlet } from 'react-router-dom'
function App() {
const [count, setCount] = useState(0)
return (
{/* 路由占位符,用于展示路由组件,和 vue 中 router-view 差不多 */}
)
}
export default App
```
#### 2. Navigate(重定向)
```js
// Navigate 重定向组件
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
}>
// 匹配到 / 路由的时候,重定向到 home 路由
} />
} />
} />
```
## 三、路由配置(对象写法)
#### 1. 展示
```js
// index
import { Navigate } from 'react-router-dom'
const routes = [
{
path: '/',
element: ,
},
{
path: '/home',
element: ,
},
{
path: '/about',
element: ,
},
]
export default routes
// main
import { BrowserRouter } from 'react-router-dom'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
// 使用 history 模式
,
)
// app
// 导入路由表
import routes from './router'
import { useRoutes } from 'react-router-dom'
function App() {
// useRoutes 接收路由表,返回当前匹配的路由元素展示对应的组件
const oulet = useRoutes(routes)
return {oulet}
}
export default App
```
#### 2. 懒加载
```js
// 引入 react 中 lazy(懒加载)函数
import React, { lazy } from 'react'
import { Navigate } from 'react-router-dom'
// 通过 lazy 方法按需导入组件
// 懒加载模式,外层需要套一层 loading 的提示加载组件
const Home = lazy(() => import('../views/Home'))
const About = lazy(() => import('../views/About'))
// 高阶组件
const withLoadingComp = (comp: JSX.Element) => (
// 只要是 lazy 懒加载模式,就必须加上 React.Suspense 组件
// fallback 组件加载前展示的内容
加载中....}>{comp}
)
const routes = [
{
path: '/',
element: ,
},
{
path: '/home',
element: withLoadingComp(),
},
{
path: '/about',
element: withLoadingComp(),
},
]
```
## 四、编程式导航
#### 1. 跳转到对应页面
```js
// 1. 导入 useNavigate 方法
import { useNavigate } from 'react-router-dom'
// 2. 接收返回的跳转方法
const navigateTo = useNavigate()
// 3. 跳转到对应页面
navigateTo('/home')
```
## 五、嵌套路由
```js
// 写法1
const routes = [
{
path: '/',
// 重定向
element: ,
},
{
path: '/',
element: ,
// 子路由,下面路由都将渲染到 home 页面上
children: [
{
path: '/about',
element: withLoadingComp(),
},
{
path: '/page',
element: withLoadingComp(),
},
],
},
]
// ts 函数写法
const getRoutes = (
path: React.Key,
element: React.ReactNode,
children?: object[],
): object => ({ path, element, children })
const routes = [
getRoutes('/', ),
getRoutes('/', , [
getRoutes('about', withLoadingComp()),
getRoutes('page', withLoadingComp()),
]),
]
```
## 六、封装路由前置守卫
```js
// permission
import { useLocation, useNavigate, useRoutes } from 'react-router-dom'
import routes from '@/router'
import { useEffect } from 'react'
import { message } from 'antd'
/*
后台管理系统两种经典的跳转情况:
1、如果访问的是登录页面, 并且有token, 跳转到首页
2、如果访问的不是登录页面,并且没有token, 跳转到登录页
3、其余的都可以正常放行
*/
// 路由守卫
const BeforeRouterEnter = () => {
const oulet = useRoutes(routes)
const navgateTO = useNavigate()
// 1. 拿到访问地址和 token
const location = useLocation()
let token = localStorage.getItem('token')
// 2. 组件加载完毕进行判断
useEffect(() => {
// 3. 如果访问的是登录页面, 并且有token, 跳转到首页
if (location.pathname === '/login' && token) {
message.success('您已经登录!')
// 进行跳转
return navgateTO('/page')
}
// 4. 如果访问的不是登录页面,并且没有token, 跳转到登录页
if (location.pathname !== '/login' && !token) {
message.error('您还未登录!')
// 进行跳转
return navgateTO('/login')
}
})
// 5. 其余正常放行
return oulet
}
export default BeforeRouterEnter
// app
import Oulet from './permission'
function App() {
return (
{/* 占位符组件,类似于窗口,用来展示组件的,有点像vue中的router-view */}
)
}
export default App
```