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

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

一、实现手动跳转路由

  1. 利用 useNavigate 封装一个 withRouter(hoc/with_router.js)
javascript 复制代码
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文件中
javascript 复制代码
import withRouter from "./with_router";
export { withRouter };
  1. 利用withRouter,拦截Home组件,实现手动跳转路由
javascript 复制代码
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()来接收两种参数传递:

javascript 复制代码
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):

javascript 复制代码
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):

javascript 复制代码
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,将所有的路由配置在此处:

javascript 复制代码
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)引入路由:

javascript 复制代码
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)

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

javascript 复制代码
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进行包裹,实现对分包加载的等待:

javascript 复制代码
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>
);

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

相关推荐
辻戋2 小时前
从零实现React Scheduler调度器
前端·react.js·前端框架
徐同保2 小时前
使用yarn@4.6.0装包,项目是react+vite搭建的,项目无法启动,报错:
前端·react.js·前端框架
Qrun3 小时前
Windows11安装nvm管理node多版本
前端·vscode·react.js·ajax·npm·html5
中国lanwp3 小时前
全局 npm config 与多环境配置
前端·npm·node.js
JELEE.4 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
TeleostNaCl6 小时前
解决 Chrome 无法访问网页但无痕模式下可以访问该网页 的问题
前端·网络·chrome·windows·经验分享
前端大卫7 小时前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友7 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理9 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design
毕设十刻9 小时前
基于Vue的学分预警系统98k51(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js