【前端知识】React 基础巩固(四十一)——手动路由跳转、参数传递及路由配置

React 基础巩固(四十一)——手动路由跳转、参数传递及路由配置

一、实现手动跳转路由

  1. 利用 useNavigate 封装一个 withRouter(hoc/with_router.js)
import {
    
     useNavigate } from "react-router-dom";
// 封装一个高阶组件
function withRouter(WrapperComponent) {
    
    
  return function (props) {
    
    
    const navigate = useNavigate();
    const router = {
    
     navigate };
    return <WrapperComponent {
    
    ...props} router={
    
    router} />;
  };
}

export default withRouter;
  1. 添加到hoc/index.js文件中
import withRouter from "./with_router";
export {
    
     withRouter };
  1. 利用withRouter,拦截Home组件,实现手动跳转路由
import React, {
    
     PureComponent } from "react";
import {
    
     Link, Outlet } from "react-router-dom";
import {
    
     withRouter } from "../hoc";

export class Home extends PureComponent {
    
    
  navigateTo(path) {
    
    
    const {
    
     navigate } = this.props.router;
    navigate(path);
  }

  render() {
    
    
    return (
      <div>
        <h1>Home</h1>
        <div className="nav">
          <Link to="/home/recommend">推荐</Link>
          <Link to="/home/ranking">排行榜</Link>
          <button onClick={
    
    (e) => this.navigateTo("/home/songmenu")}>
            歌单
          </button>
        </div>
        {
    
    /* 占位组件 */}
        <Outlet />
      </div>
    );
  }
}

export default withRouter(Home);

二、路由参数传递

路由参数传递包括:1.动态路由传参;2.查询字符串传参

改造withRouter,通过useParams()useSearchParams()来接收两种参数传递:

import {
    
    
  useLocation,
  useNavigate,
  useParams,
  useSearchParams,
} from "react-router-dom";
// 封装一个高阶组件
function withRouter(WrapperComponent) {
    
    
  return function (props) {
    
    
    // 1.导航
    const navigate = useNavigate();

    // 2.动态路由参数
    const params = useParams();

    // 3.查询字符串的参数:/user?name=test&age=18
    const location = useLocation();
    const [searchParams] = useSearchParams();
    const query = Object.fromEntries(searchParams)
    console.log(query);

    const router = {
    
     navigate, params, location, query };

    return <WrapperComponent {
    
    ...props} router={
    
    router} />;
  };
}

export default withRouter;

在界面中,通过params来接收(Detail.js):

import React, {
    
     PureComponent } from "react";
import {
    
     withRouter } from "../hoc";

export class Detail extends PureComponent {
    
    
  render() {
    
    
    const {
    
     router } = this.props;
    const {
    
     params } = router;

    return (
      <div>
        <h2>Detail</h2>
        <h2>id:{
    
    params.id}</h2>
      </div>
    );
  }
}

export default withRouter(Detail);

通过 query 来接收(User.jsx):

import React, {
    
     PureComponent } from "react";
import {
    
     withRouter } from "../hoc";

export class User extends PureComponent {
    
    
  render() {
    
    
    const {
    
     router } = this.props;
    const {
    
     query } = router;

    return (
      <div>
        <h1>
          用户:{
    
    query.name} - {
    
    query.age}
        </h1>
      </div>
    );
  }
}

export default withRouter(User);

三、路由配置文件

当前App.jsx文件中,包含Routes相关信息,过于臃肿,我们可以将Routes通过配置的形式进行引入。

构建router/index.js,将所有的路由配置在此处:

import Home from "../pages/Home";
import About from "../pages/About";
import Login from "../pages/Login";
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 HomeSangMenu from "../pages/HomeSangMenu";
import Detail from "../pages/Detail";
import User from "../pages/User";
import {
    
     Navigate } from "react-router-dom";

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: "/home/sangmenu",
        element: <HomeSangMenu />,
      },
    ],
  },
  {
    
    
    path: "/about",
    element: <About />,
  },
  {
    
    
    path: "/login",
    element: <Login />,
  },
  {
    
    
    path: "/category",
    element: <Category />,
  },
  {
    
    
    path: "/order",
    element: <Order />,
  },
  {
    
    
    path: "/detail",
    element: <Detail />,
  },
  {
    
    
    path: "/user",
    element: <User />,
  },
  {
    
    
    path: "*",
    element: <NotFound />,
  },
];
export default routes;

改写App.jsx,通过useRoutes(routes)引入路由:

import React from "react";
import {
    
    
  Link,
  NavLink,
  useNavigate,
  useRoutes,
} from "react-router-dom";
import "./style.css";
// import Home from "./pages/Home";
// import About from "./pages/About";
// import Login from "./pages/Login";
// 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 HomeSangMenu from "./pages/HomeSangMenu";
// import Detail from "./pages/Detail";
// import User from "./pages/User";
import routes from "./router";

export function App(props) {
    
    
  const navigate = useNavigate();

  function navigateTo(path) {
    
    
    console.log(path);

    navigate(path);
  }

  return (
    <div className="app">
      <div className="header">
        <span>header</span>
        <div className="nav">
          <NavLink to="/home">首页</NavLink>
          <NavLink to="/about">关于</NavLink>
          <NavLink to="/login">登陆</NavLink>

          <button onClick={
    
    (e) => navigateTo("/category")}>分类</button>
          <span onClick={
    
    (e) => navigateTo("/order ")}>订单</span>

          <Link to="/user?name=test&age=18">用户</Link>
        </div>
        <hr />
      </div>
      <div className="content">
        {
    
    /* 映射关系: path => Component */}

        {
    
    /* <Routes>
          <Route path="/" element={<Navigate to="/home" />} />
          <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 path="/home/songmenu" element={<HomeSangMenu />} />
          </Route>
          <Route path="/about" element={<About />} />
          <Route path="/login" element={<Login />} />
          <Route path="/category" element={<Category />} />
          <Route path="/order" element={<Order />} />
          <Route path="/detail/:id" element={<Detail />} />
          <Route path="/user" element={<User />} />
          <Route path="*" element={<NotFound />} />
        </Routes> */}

        {
    
    useRoutes(routes)}
      </div>
      <div className="footer">Footer</div>
    </div>
  );
}

export default App;

查看运行效果,与之前保持一致:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AByH8LHr-1690721021332)(https://gitee.com/outmanm78/markdown-image/raw/master/img/202307302029353.png)]

虽然成功抽离了路由配置信息,但是目前的方式,会导致路由统一打包,没有分包处理。我们可以进行改造一下,针对部分配置进行分包处理,实现路由懒加载:

import React from "react";
import Home from "../pages/Home";
// import About from "../pages/About";
// import Login from "../pages/Login";
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 HomeSangMenu from "../pages/HomeSangMenu";
import Detail from "../pages/Detail";
import User from "../pages/User";
import {
    
     Navigate } from "react-router-dom";

// 通过React.lazy实现About和Login界面的路由懒加载
const About = React.lazy(() => import("../pages/About"));
const Login = React.lazy(() => import("../pages/Login"));

在src/index.js中,用Suspense对App进行包裹,实现对分包加载的等待:

import React, {
    
     Suspense } from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import {
    
     HashRouter } from "react-router-dom";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <HashRouter>
      <Suspense fallback={
    
    <h3>Loading...</h3>}>
        <App />
      </Suspense>
    </HashRouter>
  </React.StrictMode>
);

查看效果,与之前保持一致,懒加载实现成功:

image-20230730204327732

猜你喜欢

转载自blog.csdn.net/weixin_42919342/article/details/132011211