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"),
);
相关推荐
可乐鸡翅yeah_4 分钟前
hls.js 播放质量埋点实战,采集卡顿、起播、错误指标定位线上用户问题
开发语言·前端·javascript·ecmascript·音视频·m3u8·音视频在线播放
传奇开心果编程5 分钟前
【Xilem 0.4 基础语法学与练】第二课视图修饰符、列表渲染、组件拆分、memoize 性能优化
学习·rust·前端框架
szarron20 分钟前
RF Demo Kit|NanoVNA 射频演示测试板完整上手教程,滤波器、衰减器、SOLT 校准学习板
开发语言·人工智能·学习·php·射频工程·频谱仪
tedcloud12324 分钟前
Wand-Enhancer:如何搭建一套远程开发与测试环境
前端·人工智能·macos·开源·流程图
边境悍匪31 分钟前
蜗牛学苑 Java 智能体学习 Day39|SpringAI 会话存储、Function‑Call 工具调用、MCP 思维导图复盘
java·开发语言·spring boot·学习·阿里云
万物智能信息科技1 小时前
RK3568 的多路显示移植—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
linux·开发语言·华为·开源·harmonyos
掘金挖土1 小时前
前端手摸手跑路之 AI 应用开发(三)
前端·后端
蓝悦无人机1 小时前
Qt Design Studio(QDS)4.8.2项目文件结构详解
开发语言·qt·qt creator·qds·项目文件结构·qtc
计算机魔术师1 小时前
OpenAI 宣称破解千禧年难题,数学家却说是「反例搜索」?
前端
志尊宝1 小时前
Vue3 零基础每日笔记(015):条件渲染 v-if 与 v-show——控制 DOM 生死还是控制显隐
前端·vue.js·笔记