只有一个html文件 主流的开发模式变成了通过路由进行页面切换 优势: 避免整体页面刷新 用户体验变好
前端负责事情变多了 开发的难度变大
概念来源于后端 : 一个路径表示匹配一个服务器资源 /a.html -> a对应的文件资源 /b.html -> b对应的文件资源
共同的思想: 一对一的关系
前端的路由: 一个路径path对应唯一的一个组件comonent 当我们访问一个path 自动把path对应的组件进行渲染
// 路由模式:声明当前要用一个非hash模式的路由
<BrowserRouter>
{/* 指定跳转的组件,to用来配置路由地址 */}
<Link to={'/home'}>首页</Link>
<Link to={'/about'}>关于</Link>
{/* 路由出口,路由对应的组件会在这里进行渲染 */}
<Routes>
{/* 指定路径和组件的对应关系,path和element成对出现 */}
<Route path="/" element={<Login />}></Route>
<Route path="/home/:id" element={<Home />}>
<Route index path="about" element={<About />}></Route>
{/* 二级路由 把自己的path干掉,添加index属性默认显示二级路由*/}
<Route index element={<About />}></Route>
<Route path="search" element={<Search />}></Route>
</Route>
{/* 当所有的路径都没有匹配到时渲染该组件 */}
<Route path="*" element={<NotFound />}></Route>
</Routes>
</BrowserRouter>
安装两个新的包
"react-dom": "^18.2.0"
"react-router-dom": "^6.11.2"
准备俩个按钮,点击不同按钮切换不同组件内容的显示
实现步骤:
// 引入必要的内置组件
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'
// 准备俩个路由组件
const Home = () => <div>this is home</div>
const About = () => <div>this is about</div>
function App() {
return (
<div className="App">
{/* 按照规则配置路由 */}
<BrowserRouter>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
</Routes>
</BrowserRouter>
</div>
)
}
export default App
作用: 包裹整个应用,一个React应用只需要使用一次
模式 | 实现方式 | 路由url表现 |
---|---|---|
HashRouter | 监听url hash值实现 | http://localhost:3000/#/about |
BrowerRouter | h5的 history.pushState API实现 | http://localhost:3000/about |
作用: 用于指定导航链接,完成声明式的路由跳转 类似于
<Link to="/about">关于</Link>
这里to属性用于指定路由地址,表示要跳转到哪里去,Link组件最终会被渲染为原生的a链接
作用: 提供一个路由出口,组件内部会存在多个内置的Route组件,满足条件的路由会被渲染到组件内部
类比 router-view
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
</Routes>
作用: 用于定义路由路径和渲染组件的对应关系 [element:因为react体系内 把组件叫做react element]
其中path属性用来指定匹配的路径地址,element属性指定要渲染的组件,图中配置的意思为: 当url上访问的地址为 /about 时,当前路由发生匹配,对应的About组件渲染
声明式 【 Link to】 vs 编程式 【调用路由方法进行路由跳转】
概念: 通过js编程的方式进行路由页面跳转,比如说从首页跳转到关于页
实现步骤:
import { useNavigate } from "react-router-dom"
export default function Login () {
// 执行useNavigate得到一个跳转函数
const nav = useNavigate()
return (
<div>
Login页面
{/* 点击跳转到home页面,并替换当前页面(默认为叠加) */}
{/* SearchParams传参 */}
{/* */}
{/* Params传参 */}
<button onClick={() => nav('/home/1001', { replace: true })}>点击登录</button>
</div>
)
}
如果在跳转时不想添加历史记录,可以添加额外参数replace 为true
跳转路由的同时,有时候要需要传递参数
传参
{/* SearchParams传参 */}
{/* */}
取参
{/* useSearchParams获取参数 */}
{params.get('id')}
传参
{/* Params传参 */}
<button onClick={() => nav('/home/1001', { replace: true })}>点击登录</button>
取参
{/* useParams获取参数 */}
{useParams().id}
在我们做的很多的管理后台系统中,通常我们都会设计一个Layout组件,在它内部实现嵌套路由
实现步骤:
APP组件路由嵌套关系
<Routes>
{/* 指定路径和组件的对应关系,path和element成对出现 */}
<Route path="/" element={<Login />}></Route>
<Route path="/home/:id" element={<Home />}>
<Route index path="about" element={<About />}></Route>
{/* 二级路由 把自己的path干掉,添加index属性默认显示二级路由*/}
<Route index element={<About />}></Route>
<Route path="search" element={<Search />}></Route>
</Route>
{/* 当所有的路径都没有匹配到时渲染该组件 */}
<Route path="*" element={<NotFound />}></Route>
</Routes>
home.js组件中使用 Outlet 组件添加二级路由出口
<div>
Home页面
{/* useSearchParams获取参数 */}
{params.get('id')}
{/* useParams获取参数 */}
{useParams().id}
<button onClick={() => nav('about')}>显示二级路由about</button>
<button onClick={() => nav('search')}>显示二级路由search</button>
{/* 二级路由出口 */}
<Outlet />
</div>
场景: 应用首次渲染完毕就需要显示的二级路由
实现步骤:
<Route path="/home/:id" element={<Home />}>
<Route index path="about" element={<About />}></Route>
{/* 二级路由 把自己的path干掉,添加index属性默认显示二级路由*/}
<Route index element={<About />}></Route>
<Route path="search" element={<Search />}></Route>
</Route>
APP组件中配置
<BrowserRouter>
<Routes>
....
{/* 当所有的路径都没有匹配到时渲染该组件 */}
<Route path="*" element={<NotFound />}></Route>
</Routes>
</BrowserRouter>
NotFound组件
export default function NotFound () {
return (
<div>
<h1>404 NotFound</h1>
</div>
)
}
场景: 当我们需要路由权限控制点时候, 对路由数组做一些权限的筛选过滤,所谓的集中式路由配置就是用一个数组统一把所有的路由对应关系写好替换 本来的Roues组件
import { BrowserRouter, Routes, Route, useRoutes } from 'react-router-dom'
import Layout from './pages/Layout'
import Board from './pages/Board'
import Article from './pages/Article'
import NotFound from './pages/NotFound'
// 1. 准备一个路由数组 数组中定义所有的路由对应关系
const routesList = [
{
path: '/',
element: <Layout />,
children: [
{
element: <Board />,
index: true, // index设置为true 变成默认的二级路由
},
{
path: 'article',
element: <Article />,
},
],
},
// 增加n个路由对应关系
{
path: '*',
element: <NotFound />,
},
]
// 2. 使用useRoutes方法传入routesList生成Routes组件
function WrapperRoutes() {
let element = useRoutes(routesList)
return element
}
function App() {
return (
<div className="App">
<BrowserRouter>
{/* 3. 替换之前的Routes组件 */}
<WrapperRoutes />
</BrowserRouter>
</div>
)
}
export default App