React系列之react-router-dom路由

1,301 阅读3分钟

一、安装依赖

yarn add react-router-dom@5.3.0

二、使用

  • react路由有两种
    • hash路由:HashRouter
    • history路由:BrowserRouter
  • 路由组件
    • Link:导航路由
    • NavLink:导航路由,可以添加高亮显示
    • Route:定义路由,即要跳转的路由
      • path:路由的路径
      • component:路由对应的组件
      • exact:路由精确匹配(当路径为 / 时,要使用 精确匹配
// 引入路由配置
// HashRouter  hash 路由
// import { HashRouter as Router, Link, Route } from "react-router-dom";

// BrowserRouter history 路由,使用html5 的 history Api,history.pushState()
import { BrowserRouter as Router, Link, Route } from "react-router-dom";

import Home from "./Home";
import Comment from "./Comment";
import Info from "./Info";
const App = () => {
  return (
    // 在顶级组件用react路由提供的组件包裹,写一次就可以,无需在每个路由的地方重复写
    <Router>
      <div>
        {/* 定义路由link,Link组件解析后变成 a 标签 */}
        <Link to="/" exact>首页</Link>
        <Link to="/comment" exact>评论</Link>
        <Link to="/info" exact>个人信息</Link>
      </div>
      <div>
        {/* 定义路由配置 */}
        <Route path="/" exact>
          <Home></Home>
        </Route>
        {/* 组件可以使用component 参数 传递 */}
        <Route path="/comment" component={Comment}></Route>
        <Route path="/info" component={Info}></Route>
      </div>
    </Router>
  );
};

export default App;

注意:若 / 路径不使用精确匹配 exact,则会出现在 /comment路径时,也会匹配到 / 路径

image.png

三、路由选中高亮显示NavLink

// 引入路由配置
import { BrowserRouter as Router, Route, NavLink } from "react-router-dom";

import Home from "./Home";
import Comment from "./Comment";
import Info from "./Info";
// 引入样式
import "./App.css";

const App = () => {
  return (
    <Router>
      <div className="nav">
        {/* 定义路由NavLink,NavLink组件解析后变成 a 标签 */}
        {/* NavLink 路由对应的 a 标签,会 自动添加 active 类名,可以通过该类名进行自定义样式 */}
        <NavLink to="/home">首页</NavLink>
        <NavLink to="/comment">评论</NavLink>
        <NavLink to="/info">个人信息</NavLink>
      </div>
      <div>
        <Route path="/home">
          <Home></Home>
        </Route>
        <Route path="/comment" component={Comment}></Route>
        <Route path="/info" component={Info}></Route>
      </div>
    </Router>
  );
};

export default App;

/* App.css */
.nav a {
  text-decoration: none;
  margin-right: 10px;
  color: skyblue;
}
.nav a.active {
  color: red;
}

image.png

四、Switch组件的使用

  • 在vue中可以通过 * 通配符进行 404 路由匹配
  • 在react中,则可以通过 Switch 组件实现
    • Switch 组件 可以简单理解为 仅匹配一次,只要匹配到了就不会再往下匹配
// 引入路由配置
import {
  BrowserRouter as Router,
  Route,
  NavLink,
  Switch,
} from "react-router-dom";

import Home from "./Home";
import Comment from "./Comment";
import Info from "./Info";
import NotFound from "./404";
// 引入样式
import "./App.css";

const App = () => {
  return (
    <Router>
      <div className="nav">
        <NavLink to="/" exact>
          首页
        </NavLink>
        <NavLink to="/comment" exact>
          评论
        </NavLink>
        <NavLink to="/info" exact>
          个人信息
        </NavLink>
      </div>
      <div>
        <Switch>
          <Route path="/" exact>
            <Home></Home>
          </Route>
          <Route path="/comment" component={Comment}></Route>
          <Route path="/info" component={Info}></Route>
          <Route component={NotFound}></Route>
        </Switch>
      </div>
    </Router>
  );
};

export default App;

image.png

五、嵌套路由

  • 即在子组件中继续使用路由嵌套

5.1 改造 评论页面

// Comment.js
import { Route, NavLink } from "react-router-dom";
import CommentA from "./Comm/ComA";
import CommentB from "./Comm/ComB";
function Comment() {
  return (
    <div>
      <div>
        <h2>这里是评论</h2>
        <NavLink to="/comment/a">CommentA</NavLink>
        <NavLink to="/comment/b" style={{ marginLeft: "20px" }}>
          CommentB
        </NavLink>
      </div>
      <div>
        <Route path="/comment/a" component={CommentA}></Route>
        <Route path="/comment/b">
          <CommentB></CommentB>
        </Route>
      </div>
    </div>
  );
}
export default Comment;

5.2 新增 评论 子页面A和B

// ComA.js
function CommentA() {
    return <div>这里是评论A</div>;
  }
  export default CommentA;
  
// ComB.js
function CommentB() {
  return <div>这里是评论B</div>;
}
export default CommentB;

5.3 效果

image.png

六、编程式导航

  • 使用 useHistory 实现 路由导航 切换

image.png 代码如下:

import { Route, NavLink, useHistory } from "react-router-dom";
import CommentA from "./Comm/ComA";
import CommentB from "./Comm/ComB";
function Comment() {
  // 引入路由 hook
  const history = useHistory();
  return (
    <div>
      <div>
        <h2>这里是评论</h2>
        <NavLink to="/comment/a">CommentA</NavLink>
        <NavLink
          to="/comment/b"
          style={{ marginLeft: "20px", marginRight: "20px" }}
        >
          CommentB
        </NavLink>
        <button
          onClick={() => {
            // 编程式导航
            console.log("history", history);
            // 跳转首页,有历史记录
            // history.push("/");
            // 跳转首页,没有历史记录,即无法使用浏览器回退键返回
            history.replace("/");
          }}
        >
          跳转首页
        </button>
      </div>
      <div>
        <Route path="/comment/a" component={CommentA}></Route>
        <Route path="/comment/b">
          <CommentB></CommentB>
        </Route>
      </div>
    </div>
  );
}
export default Comment;

七、路由传参

7.1 改造 index.js

import React from "react";
import { createRoot } from "react-dom/client";
import store from "./store";
import App from "./App";
import { Provider } from "react-redux";
// 引入路由 最顶级组件包裹
import { BrowserRouter as Router } from "react-router-dom";

const root = createRoot(document.getElementById("root"));
root.render(
  <Router>
    <Provider store={store}>
      <App></App>
    </Provider>
  </Router>
);

7.1 改造 App.js

// 引入路由配置
import { Route, NavLink, Switch, useHistory } from "react-router-dom";

import Home from "./Home";
import Comment from "./Comment";
import Info from "./Info";
import NotFound from "./404";
// 引入样式
import "./App.css";

const App = () => {
  // 路由 hook
  const history = useHistory();
  console.log("history", history);

  return (
    <div>
      <div className="nav">
        <NavLink to="/" exact>
          首页
        </NavLink>
        <NavLink to="/comment" exact>
          评论
        </NavLink>
        <NavLink to="/info">个人信息</NavLink>
        <button
          onClick={() => {
            console.log("history", history);
            history.push("/info/666");
          }}
        >
          跳转个人信息页,带参数
        </button>
      </div>
      <div>
        <Switch>
          <Route path="/" exact>
            <Home></Home>
          </Route>
          <Route path="/comment" component={Comment}></Route>
          {/* 修改路由 */}
          <Route path="/info/:id" component={Info}></Route>
          <Route component={NotFound}></Route>
        </Switch>
      </div>
    </div>
  );
};

export default App;

7.3 效果

  • 若不传参数

image.png

  • 传参数

image.png

7.4 改造个人信息组件,获取路由参数

import { useParams } from "react-router-dom";
function Info() {
  // 使用 hook
  const params = useParams();
  console.log("路由参数", params);

  return (
    <div>
      <h2>这里是个人信息</h2>
    </div>
  );
}
export default Info;

image.png