React - 路由样式丢失问题、路由观察记录、路由传递参数

一、路由样式丢失问题

1、问题复现
(1)html
  1. public/index.html
html 复制代码
...

<link rel="stylesheet" href="./css/myStyle.css">

...
  1. public/css/myStyle.css
css 复制代码
.my-box {
    border: 1px solid red;
    background-color: skyblue;
}
(2)component
  • MyNavLink 组件
js 复制代码
import React, { Component } from "react";
import { NavLink } from "react-router-dom";
import "./index.css";

export default class MyNavLink extends Component {
    render() {
        return <NavLink activeClassName="selected" className="list-group-item" {...this.props} />;
    }
}
css 复制代码
.active {
    color: red;
    font-weight: bold;
    background-color: #f0f0f0;
}

.selected {
    color: blue;
    font-weight: bold;
    background-color: #f0f0f0;
}
(3)page
  1. About 页面
js 复制代码
import React, { Component } from "react";

export default class About extends Component {
    render() {
        return <h3 className="my-box">About Content</h3>;
    }
}
  1. Home 页面
js 复制代码
import React, { Component } from "react";

export default class Home extends Component {
    render() {
        return <h3 className="my-box">Home Content</h3>;
    }
}
(4)main
  1. App 组件
js 复制代码
import React, { Component } from "react";
import { Route, Switch } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import MyNavLink from "./components/MyNavLink/index";

export default class App extends Component {
    render() {
        return (
            <div>
                <h2>React Router Demo</h2>
                <div>
                    <MyNavLink to="/test/about">About</MyNavLink>
                    <MyNavLink to="/test/home">Home</MyNavLink>
                </div>
                <div>
                    <Switch>
                        <Route path="/test/about" component={About} />
                        <Route path="/test/home" component={Home} />
                    </Switch>
                </div>
            </div>
        );
    }
}
  1. index.js
js 复制代码
import React from "react"; // 引入 React 核心库
import ReactDOM from "react-dom"; // 引入 ReactDOM
import App from "./App"; // 引入 App 组件
import { BrowserRouter } from "react-router-dom";

// 渲染 App 组件到页面
ReactDOM.render(
    <BrowserRouter>
        <App />
    </BrowserRouter>,
    document.getElementById("root"),
);
(5)test
  1. 访问 http://localhost:3000,样式生效

    此时请求样式的路径为

    http://localhost:3000/css/myStyle.css

  2. 访问 http://localhost:3000/test/about,样式丢失

    此时请求样式的路径为

    http://localhost:3000/test/css/myStyle.css

2、处理策略
  • 使用 %PUBLIC_URL% 环境变量
html 复制代码
<link rel="stylesheet" href="%PUBLIC_URL%/css/myStyle.css">
3、访问路径小结
  1. http://localhost:3000 相当于 public 目录

  2. 可以指定路径以访问 public 目录下的文件,例如,http://localhost:3000/favicon.ico,会返回 public 目录下的 favicon.ico 文件

  3. 如果没有指定路径,或者指定一个不存在的路径,默认会返回 public 目录下的 index.html 文件


二、路由观察记录

1、基础路由
(1)演示
js 复制代码
import React, { Component } from "react";
import { Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import MyNavLink from "./components/MyNavLink/index";

export default class App extends Component {
    render() {
        return (
            <div>
                <h2>React Router Demo</h2>
                <div>
                    <MyNavLink to="/about">About</MyNavLink>
                    <MyNavLink to="/home">Home</MyNavLink>
                </div>
                <div>
                    <Route path="/about" component={About} />
                    <Route path="/home" component={Home} />
                </div>
            </div>
        );
    }
}
  1. 访问 http://localhost:3000,访问正常

  2. 访问 http://localhost:3000/about,访问正常

  3. 访问 http://localhost:3000/home,访问正常

(2)小结
  • 多个 Route 可以同时匹配
2、错误的 Redirect
(1)演示
js 复制代码
import React, { Component } from "react";
import { Route, Redirect } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import MyNavLink from "./components/MyNavLink/index";

export default class App extends Component {
    render() {
        return (
            <div>
                <h2>React Router Demo</h2>
                <div>
                    <MyNavLink to="/about">About</MyNavLink>
                    <MyNavLink to="/home">Home</MyNavLink>
                </div>
                <div>
                    <Route path="/about" component={About} />
                    <Route path="/home" component={Home} />
                    <Redirect path="/about" />
                </div>
            </div>
        );
    }
}
  1. 访问 http://localhost:3000,访问正常

  2. 访问 http://localhost:3000/about,跳转到 http://localhost:3000

  3. 访问 http://localhost:3000/home,跳转到 http://localhost:3000

(2)小结
  1. 多个 Route 可以同时匹配

  2. 访问 /about 时,先匹配到 <Route path="/about">,继续匹配到错误的 <Redirect path="/about">,React Router 可能将其解析为某种重定向逻辑

  3. 访问 /home 时,先匹配到 <Route path="/home">,继续匹配到错误的 <Redirect path="/about">,React Router 可能将其解析为某种重定向逻辑

3、Switch + 错误的 Redirect
(1)演示
js 复制代码
import React, { Component } from "react";
import { Route, Switch, Redirect } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import MyNavLink from "./components/MyNavLink/index";

export default class App extends Component {
    render() {
        return (
            <div>
                <h2>React Router Demo</h2>
                <div>
                    <MyNavLink to="/about">About</MyNavLink>
                    <MyNavLink to="/home">Home</MyNavLink>
                </div>
                <div>
                    <Switch>
                        <Route path="/about" component={About} />
                        <Route path="/home" component={Home} />
                        <Redirect path="/about" />
                    </Switch>
                </div>
            </div>
        );
    }
}
  1. 访问 http://localhost:3000,访问正常

  2. 访问 http://localhost:3000/about,访问正常

  3. 访问 http://localhost:3000/home,访问正常

(2)小结
  1. Switch 只渲染第一个匹配到的组件

  2. 访问 /about 时,第一个匹配的是 <Route path="/about">,渲染 About 后就停止了,错误的 Redirect 没有被处理

  3. 访问 /home 时,第一个匹配的是 <Route path="/home">,渲染 Home 后就停止了,错误的 Redirect 没有被处理

4、正确的 Redirect
(1)演示
js 复制代码
import React, { Component } from "react";
import { Route, Redirect } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import MyNavLink from "./components/MyNavLink/index";

export default class App extends Component {
    render() {
        return (
            <div>
                <h2>React Router Demo</h2>
                <div>
                    <MyNavLink to="/about">About</MyNavLink>
                    <MyNavLink to="/home">Home</MyNavLink>
                </div>
                <div>
                    <Route path="/about" component={About} />
                    <Route path="/home" component={Home} />
                    <Redirect to="/about" />
                </div>
            </div>
        );
    }
}
  1. 访问 http://localhost:3000,跳转到 http://localhost:3000/about

  2. 访问 http://localhost:3000/about,访问正常

  3. 访问 http://localhost:3000/home,跳转到 http://localhost:3000/about

(2)小结
  1. 多个 Route 可以同时匹配

  2. 访问 /about 时,先匹配到 <Route path="/about">,继续匹配 <Redirect to="/about" />

  3. 访问 /home 时,先匹配到 <Route path="/home">,继续匹配 <Redirect to="/about" />

5、Switch + 正确的 Redirect
(1)演示
js 复制代码
import React, { Component } from "react";
import { Route, Switch, Redirect } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import MyNavLink from "./components/MyNavLink/index";

export default class App extends Component {
    render() {
        return (
            <div>
                <h2>React Router Demo</h2>
                <div>
                    <MyNavLink to="/about">About</MyNavLink>
                    <MyNavLink to="/home">Home</MyNavLink>
                </div>
                <div>
                    <Switch>
                        <Route path="/about" component={About} />
                        <Route path="/home" component={Home} />
                        <Redirect to="/about" />
                    </Switch>
                </div>
            </div>
        );
    }
}
  1. 访问 http://localhost:3000,跳转到 http://localhost:3000/about

  2. 访问 http://localhost:3000/about,访问正常

  3. 访问 http://localhost:3000/home,访问正常

(2)小结
  1. Switch 只渲染第一个匹配到的组件

  2. 访问 /about 时,第一个匹配的是 <Route path="/about">,渲染 About 后就停止了

  3. 访问 /home 时,第一个匹配的是 <Route path="/home">,渲染 Home 后就停止了


三、路由传递参数

1、基本介绍
  1. params 参数:适合传递必须参数,例如,ID、用户名等

  2. search 参数:适合可选参数、过滤条件等

  3. state 参数:适合传递复杂数据、敏感信息,不会显示在 URL 中

2、演示
(1)page
  1. Message 页面
js 复制代码
import React, { Component } from "react";
import { Link, Route } from "react-router-dom";
import Detail from "./Detail";
import News from "./News";
import Tip from "./Tip";

export default class Message extends Component {
    state = {
        messageArr: [
            { id: "01", title: "消息 1" },
            { id: "02", title: "消息 2" },
            { id: "03", title: "消息 3" },
        ],
    };

    render() {
        const { messageArr } = this.state;
        return (
            <div>
                <h3>传递 params 参数</h3>
                <ul>
                    {messageArr.map((msgObj) => {
                        return (
                            <li key={msgObj.id}>
                                <Link to={`/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
                            </li>
                        );
                    })}
                </ul>
                <Route path="/message/detail/:id/:title" component={Detail} />

                <h3>传递 search 参数</h3>
                <ul>
                    {messageArr.map((msgObj) => {
                        return (
                            <li key={msgObj.id}>
                                <Link to={`/message/news/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>
                            </li>
                        );
                    })}
                </ul>
                <Route path="/message/news" component={News} />

                <h3>传递 state 参数</h3>
                <ul>
                    {messageArr.map((msgObj) => {
                        return (
                            <li key={msgObj.id}>
                                <Link to={{ pathname: "/message/tip", state: { id: msgObj.id, title: msgObj.title } }}>{msgObj.title}</Link>
                            </li>
                        );
                    })}
                </ul>
                <Route path="/message/tip" component={Tip} />
            </div>
        );
    }
}
  1. Detail 页面
js 复制代码
import React, { Component } from "react";

export default class Detail extends Component {
    render() {
        const { id, title } = this.props.match.params;
        return (
            <ul>
                <li>id: {id}</li>
                <li>title: {title}</li>
            </ul>
        );
    }
}
  1. News 页面
js 复制代码
import React, { Component } from "react";
import qs from "qs";

export default class News extends Component {
    render() {
        const { search } = this.props.location;
        const { id, title } = qs.parse(search.slice(1));
        return (
            <ul>
                <li>id: {id}</li>
                <li>title: {title}</li>
            </ul>
        );
    }
}
  1. Tip 页面
js 复制代码
import React, { Component } from "react";

export default class Tip extends Component {
    render() {
        const { id, title } = this.props.location.state || {};
        return (
            <ul>
                <li>id: {id}</li>
                <li>title: {title}</li>
            </ul>
        );
    }
}
(2)main
  1. App 组件
js 复制代码
import React, { Component } from "react";
import { Route } from "react-router-dom";
import Message from "./pages/Message";

export default class App extends Component {
    render() {
        return (
            <div>
                <Route path="/message" component={Message} />
            </div>
        );
    }
}
  1. index.js
js 复制代码
import React from "react"; // 引入 React 核心库
import ReactDOM from "react-dom"; // 引入 ReactDOM
import App from "./App"; // 引入 App 组件
import { BrowserRouter } from "react-router-dom";

// 渲染 App 组件到页面
ReactDOM.render(
    <BrowserRouter>
        <App />
    </BrowserRouter>,
    document.getElementById("root"),
);
相关推荐
JieE2126 小时前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
runnerdancer7 小时前
LLM是怎么处理messages数组的,提示词缓存又是什么
前端·agent
陈随易7 小时前
VSCode的Copilot扩展支持接入DeepSeek,Kimi了!
前端·后端·程序员
我不是外星人9 小时前
有了 Harness Engineering ,真的还需要研发工程师吗?
前端·后端·ai编程
candyTong9 小时前
RTK 技术原理:一次典型会话里,80% 上下文是怎么省下来的
javascript·后端·架构
IT_陈寒11 小时前
JavaScript的闭包把我坑惨了,说好的内存会自动回收呢?
前端·人工智能·后端
Jackson__12 小时前
分享一个横向滚动案例,带悬停暂停,通用性很强
前端
MariaH13 小时前
git rebase的使用
前端
_柳青杨13 小时前
深入理解 JavaScript 事件循环
前端·javascript
阡陌Jony13 小时前
关于前端性能优化的一些问题:
前端