前端路由的功能:让用户从一个页面跳转到另一个页面。
前端路由是一套映射规则,在 React 中,是 URL 路径与组件的对应关系。
使用 React 路由简单来说就是配置路径与组件(配对)。
路由的本质: 一个路径 path 对应唯一的一个组件 component 当我们访问一个 path 自动把 path 对应的组件进行渲染。
首先你需要有一个 React 项目:npx create-react-app my-app (这是 React 脚手架初始化项目)
注:React 路由使用前需要先安装 react-router-dom 的包,React 脚手架初始化项目时不会自动安装这个包,需要我们手动再安装
安装包:yarn add react-router-dom 或 npm i react-router-dom@6
(注:本文使用的 react-router-dom 版本为 ^6.3.0)
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'
说明:
BrowerRouter:包裹整个应用,一个 React 应用只需要使用一次,这个组件可以和 HashRouter 替换,二者主要区别如下:
模式 | 实现方式 | 路由url表现 |
HashRouter | 监听url hash值实现 | http://localhost:3000/#/about |
BrowerRouter | h5的 history.pushState API实现 | http://localhost:3000/about |
Route:用于定义路由路径 path 和渲染组件 element 的对应关系 [element:因为 react 体系内把组件叫做 react element]
- import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'
-
- function Home () {
- return (
- <p>这是首页的内容p>
- )
- }
- function About () {
- return (
- <p>这是关于的内容p>
- )
- }
- function App () {
- return (
- // 声明当前要用一个非hash模式的路由
- <BrowserRouter>
- <div className="App">
- {/* 指定跳转的组件,to 用来配置路由地址 */}
- <Link to="/">首页Link><br />
- <Link to="/about">关于Link>
- {/* 路由出口:路由对应的组件会在这里进行渲染 */}
- <Routes>
- {/* 指定路由路径和组件的对应关系:path 代表路径,element 代表对应的组件,它们成对出现 */}
- <Route path='/' element={<Home />}>Route>
- <Route path='/about' element={<About />}>Route>
- Routes>
- div>
- BrowserRouter>
- )
- }
-
- export default App
注:上面使用 跳转 的方式是:声明式导航
编程式导航: 通过 js 编程的方式进行路由页面跳转,比如说从首页跳转到关于页
- // 导入useNavigate函数
- import { useNavigate } from 'react-router-dom'
- const Home = () => {
- // 执行函数
- const navigate = useNavigate()
- return (
- <div>
- Home
- <button onClick={ ()=> navigate('/about') }> 跳转关于页 button>
- div>
- )
- }
-
- export default Home
注: 如果在跳转时不想添加历史记录,可以添加额外参数 replace 为 true
navigate('/about', { replace: true } )
跳转路由的同时,很多时候都需要传递参数,这里有两种传参方式:
路由传参
navigate('/?id=1001&name=zs', { replace: true })
路由取参
- import { useSearchParams } from 'react-router-dom'
- // 在Home中读取页面传递过来的参数(以路径拼接的方式传递过来的参数)
- function Home () {
- const [params] = useSearchParams()
- // params 是一个对象,对象里有一个get方法用来获取对应的参数
- // 把参数的名称作为get方法的实参传递即可
- const id = params.get('id')
- const name = params.get('name')
- return (
- <p>这是首页的内容,首页获取到的参数id:{id},name:{name}p>
- )
- }
路由传参
navigate('/about/1002/lisi', { replace: true })
设置参数占位符
- {/* 使用 params 传参和接收参数时,指定路由路径时需要提前使用“占位符”给参数进行占位 */}
- <Route path='/about/:id/:name' element={<About />}>Route>
路由取参
- import { useParams } from 'react-router-dom'
- // 在关于页面接收登录页使用 params 传参的方式传递过来的参数
- function About () {
- const params = useParams()
- return (
- <p>这是关于的内容,接收到登录页传递过来的id为:{params.id},name为{params.name}p>
- )
- }
注:以上两种路由传参的方式各有优劣,没有说一定要使用哪一种,个人根据习惯使用即可。
- import { BrowserRouter, Routes, Route, Link, Outlet } from 'react-router-dom'
- const Home = () => {
- return (
- <div>
- <p>首页p>
- <Link to='/'>to boardLink><br />
- <Link to='/artacle'>to artacleLink><br />
- {/* 定义二级路由出口,嵌套的路由对应组件将渲染到此处 */}
- <Outlet />
- div>
- )
- }
- const Board = () => {
- return (
- <div>这是 Board 组件,这是默认显示的二级组件div>
- )
- }
- const Artacle = () => {
- return (
- <div>这是 Artacle 组件div>
- )
- }
- function App () {
- return (
- <BrowserRouter>
- <div className="App">
- <Routes>
- {/* 一级路由 */}
- <Route path='/' element={<Home />}>
- {/* 在一级路由内部嵌套二级路由 */}
- {/* 默认二级:添加 index 属性,把它自己的 path 去掉即可 */}
- <Route index element={<Board />}>Route>
- {/* <Route path='board' element={<Board />}>Route> */}
- <Route path='artacle' element={<Artacle />}>Route>
- Route>
- Routes>
- div>
- BrowserRouter>
- )
- }
-
- export default App
注:默认二级路由:(见示例代码)
实现步骤:
场景:当 url 的路径在整个路由配置中都找不到对应的 path ,使用404兜底组件进行渲染。
- import { BrowserRouter, Routes, Route } from 'react-router-dom'
-
- // 定义 404 组件
- const NotFound = () => {
- return (
- <h1>404 抱歉,页面未找到TATh1>
- )
- }
- function App () {
- return (
- <BrowserRouter>
- <div className="App">
- <Routes>
- {/* 一级路由 */}
- {/* 当所有路径都没有匹配到时渲染此组件 作为兜底 */}
- <Route path='*' element={<NotFound />}>Route>
- Routes>
- div>
- BrowserRouter>
- )
- }
-
- export default App
场景: 当我们需要路由权限控制点时候, 对路由数组做一些权限的筛选过滤,所谓的集中式路由配置就是用一个数组统一把所有的路由对应关系写好替换本来的 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