一、

2、
# 使用CRA创建项目 npx create-react-app react-router-pro cd react-router-pro # 安装最新的ReactRouter包 npm i react-router-dom # 启动项目 npm run start
3、

import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import { createBrowserRouter,RouterProvider } from 'react-router-dom'; // 创建router实例对象,并且配置路由对应关系 const router = createBrowserRouter([ { path: '/login', element: <div>我是登录页面</div> }, { path: '/article', element: <div>我是文章页面</div> } ]) const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <RouterProvider router={router}/> {/* <App /> */} </React.StrictMode> ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
效果:

上面的代码有两个问题:
(1)、通常路由对应的组件非常复杂,不是一个简单的元素div,通常是一个组件
(2)、直接把路由放到入口的index.js文件中是不合理的,通常时放到router模块

(1)、新增Login组件和Article组件,这个组件称为路由级别的组件,专门和路由进行绑定
在src目录下新建page文件夹,在page目录下新建Login目录和Article目录(通常除了js文件,还有样式文件),各自新增index.js文件
Article/index.js文件的内容如下:
const Article =() => { return <div>我是文章页</div> } export default Article
Login/index.js文件的内容如下:
const Login =() => { return <div>我是登录页</div> } export default Login
目录结构如下:

(2)、创建一个router模块,把第一步创建的组件引进来,配置path和component,
在src目录下创建router目录,router目录下创建index.js文件,内容如下:
import Login from '../page/Login' import Article from '../page/Article' import { createBrowserRouter } from 'react-router-dom' const router = createBrowserRouter([ { path: '/login', element: <Login/> }, { path: '/article', element: <Article/> } ]) export default router
(3)、通过RouterProvider注入router实例
src/index.js文件内容如下:
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import reportWebVitals from './reportWebVitals'; import { RouterProvider } from 'react-router-dom'; import router from './router' const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <RouterProvider router={router}/> {/* <App /> */} </React.StrictMode> ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
二、

我们已经完成了登录页和文章页两个路由,假设在登录页中有一个Button按钮,点击Button按钮的时候跳转到文章页,
修改Login/index.js文件
import {Link} from 'react-router-dom'
const Login =() => {
return (
<div>
我是登录页
<Link to="/article">跳转到文章页</Link>
</div>
)
}
export default Login
效果如下:


2、
<Link to="/article">文章</Link>
语法说明:通过给组件的to属性指定要跳转到路由path,组件会被渲染为浏览器支持的a链接,如果需要传参直接通过字符串拼接的方式拼接参数即可
import { useNavigate } from "react-router-dom"
const Login =() => {
const navigate = useNavigate()
return (
<div>
我是登录页
<button onClick={()=>{navigate('/article')}}>跳转至文章页</button>
</div>
)
}
export default Login
语法说明:通过调用navigate方法传入地址path实现跳转

1、searchParams传参
接收参数的时候用到固定的钩子函数useSearchParams
Login/index.js
import { useNavigate } from "react-router-dom"
const Login =() => {
const navigate = useNavigate()
return (
<div>
我是登录页
<button onClick={()=>{navigate('/article?id=1001&name=jack')}}>跳转至文章页</button>
</div>
)
}
export default Login
Article/index.js
import {useSearchParams} from "react-router-dom"
const Article =() => {
const [params] = useSearchParams()
const id = params.get('id')
const name = params.get('name')
return <div>我是文章页-{id}-{name}</div>
}
export default Article
效果:

2、Params传参
Login/index.js
import { useNavigate } from "react-router-dom"
const Login =() => {
const navigate = useNavigate()
return (
<div>
我是登录页
<button onClick={()=>{navigate('/article/1001')}}>跳转至文章页</button>
</div>
)
}
export default Login
修改router/index.js
import Login from '../page/Login' import Article from '../page/Article' import { createBrowserRouter } from 'react-router-dom' const router = createBrowserRouter([ { path: '/login', element: <Login/> }, { path: '/article/:id', element: <Article/> } ]) export default router
Article/index.js
import {useParams} from "react-router-dom"
const Article =() => {
const params = useParams()
let id = params.id
return <div>我是文章页-{id}</div>
}
export default Article
效果如下:

如果还想传递一个name参数,则相应修改如下:
Login/index.js
<button onClick={()=>{navigate('/article/1001/jack')}}>跳转至文章页</button>
router/index.js
{ path: '/article/:id/:name', element: <Article/> }
Article/index.js
import {useParams} from "react-router-dom"
const Article =() => {
const params = useParams()
let id = params.id
let name = params.name
return <div>我是文章页-{id}-{name}</div>
}
export default Article
三、

上图是一个后台管理系统,Layout component为一级路由,左侧是一个菜单,右侧是一个二级路由出口。当点击看板的时候,二级路由出口会显示看板对应的二级路由组件内容,当点击关于的时候,又会切换到关于组件的内容
2、
实现步骤
-
使用
children属性配置路由嵌套关系 -
使用
<Outlet/>组件配置二级路由渲染位置

page目录下新建Layout目录,然后Layout目录下再新建index.js,内容如下:
const Layout = ()=>{ return( <div> 我是一级路由Layout组件 </div> ) } export default Layout
page目录下新建About目录,然后About目录下再新建index.js,内容如下:
const About = ()=>{ return ( <div> 我是关于页 </div> ) } export default About
page目录下新建Board目录,然后Board目录下再新建index.js,内容如下:
const Board = ()=>{ return ( <div> 我是面板页 </div> ) } export default Board
在router/index.js中配置嵌套路由
import Login from '../page/Login' import Article from '../page/Article' import Layout from '../page/Layout' import Board from '../page/Board' import About from '../page/About' import { createBrowserRouter } from 'react-router-dom' import Board from '../page/Board' const router = createBrowserRouter([ { path: '/', element: <Layout/>, children: [ { path: 'board', element: <Board/> }, { path: 'about', element: <About/> } ] }, { path: '/login', element: <Login/> }, { path: '/article/:id/:name', element: <Article/> } ]) export default router
在Layout/index.js中使用‘<Outlet/>’组件配置二级路由渲染位置
import {Link,Outlet} from 'react-router-dom' const Layout = ()=>{ return( <div> 我是一级路由Layout组件 <Link to="/board">看板</Link> <Link to="/about">关于</Link> {/* 配置二级路由的出口 */} <Outlet/> </div> ) } export default Layout
效果:

3、
当访问的是一级路由时,默认的二级路由组件可以得到渲染,只需要在二级路由的位置去掉path,设置index属性为true

import Login from '../page/Login' import Article from '../page/Article' import Layout from '../page/Layout' import Board from '../page/Board' import About from '../page/About' import { createBrowserRouter } from 'react-router-dom' const router = createBrowserRouter([ { path: '/', element: <Layout/>, children: [ { // path: 'board', index: true, element: <Board/> }, { path: 'about', element: <About/> } ] }, { path: '/login', element: <Login/> }, { path: '/article/:id/:name', element: <Article/> } ]) export default router
效果如下:

由于router/index.js中去掉了/board,此时还需要修改Layout/index.js,将看板的路由改为/
import {Link,Outlet} from 'react-router-dom'
const Layout = ()=>{
return(
<div>
我是一级路由Layout组件
<Link to="/">看板</Link>
<Link to="/about">关于</Link>
{/* 配置二级路由的出口 */}
<Outlet/>
</div>
)
}
export default Layout
4、
场景:当浏览器输入url的路径在整个路由配置中都找不到对应的 path,为了用户体验,可以使用 404 兜底组件进行渲染
实现步骤:
-
准备一个NotFound组件
-
在路由表数组的末尾,以*号作为路由path配置路由,*号表示通配符,表示如果上面的地址都无法匹配,则有它来匹配

在page目录下创建notFound目录,该目录下新建index.js文件,内容如下:
const NotFound = ()=>{ return ( <div> this is NotFound </div> ) } export default NotFound
修改router/index.js
import Login from '../page/Login' import Article from '../page/Article' import Layout from '../page/Layout' import Board from '../page/Board' import About from '../page/About' import NotFound from '../page/NotFound' import { createBrowserRouter } from 'react-router-dom' const router = createBrowserRouter([ { path: '/', element: <Layout/>, children: [ { // path: 'board', index: true, element: <Board/> }, { path: 'about', element: <About/> } ] }, { path: '/login', element: <Login/> }, { path: '/article/:id/:name', element: <Article/> }, { path: '*', element: <NotFound/> } ]) export default router
效果如下:

5、
各个主流框架的路由常用的路由模式有俩种,history模式和hash模式, ReactRouter分别由 createBrowerRouter 和 createHashRouter 函数负责创建
| url表现 | 底层原理 | 是否需要后端支持 | |
|---|---|---|---|
| history | url/login | history对象 + pushState事件 | 需要 |
| hash | url/#/login | 监听hashChange事件 | 不需要 |
之前讲过createBrowserRouter,现在来演示createHashRouter,直接替换即可
import Login from '../page/Login' import Article from '../page/Article' import Layout from '../page/Layout' import Board from '../page/Board' import About from '../page/About' import NotFound from '../page/NotFound' import { createBrowserRouter,createHashRouter } from 'react-router-dom' const router = createHashRouter([ { path: '/', element: <Layout/>, children: [ { // path: 'board', index: true, element: <Board/> }, { path: 'about', element: <About/> } ] }, { path: '/login', element: <Login/> }, { path: '/article/:id/:name', element: <Article/> }, { path: '*', element: <NotFound/> } ]) export default router
效果如下:

浙公网安备 33010602011771号