文章目录

      • 路由的参数传递
      • 路由的配置文件

路由的参数传递

传递参数有二种方式(需要注意的是, 这两种方式在Router6.x中都是提供的hook函数的API, 类组件需要通过高阶组件的方式使用):

动态路由的方式;

search传递参数(查询字符串);

方式一: 动态路由的概念指的是路由中的路径并不会固定:

比如/detail的path对应一个组件Detail;

如果我们将path在Route匹配时写成/detail/:id,那么 /detail/111、/detail/123都可以匹配到该Route,并且进行显示;

这个匹配规则,我们就称之为动态路由;

通常情况下,使用动态路由可以为路由传递参数。

  • 配置动态路由
render() {  return (    <div className='app'>      <div className='header'>        <Link to="detail/123">详情123</Link>        <Link to="detail/321">详情321</Link>        <Link to="detail/aaa">详情aaa</Link>      </div>      <div className='counter'>        <Routes>          <Route path='/detail/:id' element={<Detail/>}/>        </Routes>      </div>      <div className='footer'>footer</div>    </div>  )}
  • 在跳转的页面中可以通过hook函数useParms获取到传入的id, 由于我们现在使用的是类组件, 无法使用hook函数, 因此需要通过高阶组件对当前组件增强(上一篇刚刚讲过高阶组件的封装, 这里直接使用, 给到大家代码)
import { useNavigate, useParams } from "react-router-dom"export default function withRouter(WrapperComponent) {  return function(props) {    const naviagte = useNavigate()    const params = useParams()    const router = {naviagte, params}    return <WrapperComponent {...props} router={router} />  }}
  • 使用高阶组件增强当前Detail组件, 就可以通过useParams获取到传递的id
import React, { PureComponent } from 'react'import withRouter from '../hoc/with_router'export class Detail extends PureComponent {  render() {    // 获取到params    const { params } = this.props.router    return (      <div>        <h2>Detail</h2>        {/* 通过params获取到id并展示 */}        <h2>id: {params.id}</h2>      </div>    )  }}export default withRouter(Detail)

方式二: search传递参数(也就是查询字符串的方式), 这里在User组件中进行演示

  • 在路由跳转时拼接上查询字符串
render() {  return (    <div className='app'>      <div className='header'>        <Link to="/user?name=chenyq&age=18&height=1.88">用户</Link>      </div>      <div className='counter'>        <Routes>          <Route path='/user' element={<User/>} />        </Routes>      </div>      <div className='footer'>footer</div>    </div>  )}
  • 查询字符串需要通过hook函数useSearchParams获取, 所以我们也需要使用高阶组件对User组件进行增强
// 封装的高阶组件import { useNavigate, useParams, useSearchParams } from "react-router-dom"export default function withRouter(WrapperComponent) {  return function(props) {    // 1.导航    const naviagte = useNavigate()    // 2.动态路由的参数    const params = useParams()    // 3.查询字符串的参数    const [searchParams] = useSearchParams()    const query = Object.fromEntries(searchParams.entries)    const router = {naviagte, params, query}    return <WrapperComponent {...props} router={router} />  }}
  • 在组件中就可以获取到参数
import React, { PureComponent } from 'react'import withRouter from '../hoc/with_router'export class User extends PureComponent {  render() {    // 获取高阶组件中的query    const { query } = this.props.router    return (      <div>        <h2>User</h2>        {/* 通过query获取参数 */}        <h2>参数: {query.name}-{query.age}-{query.height}</h2>      </div>    )  }}export default withRouter(User)

路由的配置文件

目前我们所有的路由定义都是直接使用Route组件,并且添加属性来完成的

但是这样的方式会让路由变得非常混乱,我们希望像vue-router那样, 将所有的路由配置放到一个单独的文件进行集中管理:

在早期的时候,Router并且没有提供相关的API,我们需要借助于react-router-config完成;

在Router6.x中,为我们提供了useRoutes API可以完成相关的配置;

例如我们将下面的映射关系配置到一个单独的文件中

<div className='counter'>  <Routes>    {/* 当默认路径 / 时, 重定向到home页面 */}    <Route path='/' element={<Navigate to="/home"/>}></Route>    {/* 配置二级路由 */}    <Route path='/home' element={<Home/>}>      <Route path='/home' element={<Navigate to="/home/recommend"/>}/>      <Route path='/home/recommend' element={<HomeRecommend/>}/>      <Route path='home/ranking' element={<HomeRanking/>}/>    </Route>    <Route path='/about' element={<About/>}/>    <Route path='/profile' element={<Profile/>}/>    <Route path='/category' element={<Category/>}/>    <Route path='/order' element={<Order/>}/>    <Route path='/detail/:id' element={<Detail/>}/>    <Route path='/user' element={<User/>} />    {/* 当上面路径都没有匹配到时, 显式Notfound组件 */}    <Route path='*' element={<Notfound/>}/>  </Routes></div>

首先, 使用useRoutes这个API替代原来的Routes和Route组件, useRoutes可以当成一个函数直接使用, 但是只能在函数组件中使用

<div className='counter'>  {useRoutes(routes)}</div>

再在route/index.js中对映射关系进行配置

import { Navigate } from "react-router-dom"import Home from '../pages/Home'import About from '../pages/About'import Profile from '../pages/Profile'import Notfound from '../pages/Notfound'import HomeRecommend from '../pages/HomeRecommend'import HomeRanking from '../pages/HomeRanking'import Category from '../pages/Category'import Order from '../pages/Order'import Detail from '../pages/Detail'import User from '../pages/User'const routes = [  {    path: "/",    element: <Navigate to="/home"/>  },  {    path: "/home",    element: <Home/>,    children: [      {        path: "/home",        element: <Navigate to="/home/recommend" />      },      {        path: "/home/recommend",        element: <HomeRecommend/>      },      {        path: "/home/ranking",        element: <HomeRanking/>      }    ]  },  {    path: "/about",    element: <About/>  },  {    path: "/profile",    element: <Profile/>  },  {    path: "/category",    element: <Category/>  },  {    path: "/order",    element: <Order/>  },  {    path: "detail/:id",    element: <Detail/>  },  {    path: "/user",    element: <User/>  },  {    path: "*",    element: <Notfound/>  }]export default routes

如果我们对某些组件进行了异步加载(懒加载, 分包处理),那么需要使用Suspense进行包裹:

例如我们对Detail和User进行懒加载(分包处理)

// import Detail from '../pages/Detail'// import User from '../pages/User'const Detail = React.lazy(() => import("../pages/Detail"))const User = React.lazy(() => import("../pages/User"))

并且还需要使用Suspense对组件进行包裹

root.render(  <HashRouter>    <Suspense fallback={<h3>loading</h3>}>      <App/>    </Suspense>  </HashRouter>)