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"),
);
相关推荐
英俊潇洒美少年2 小时前
React类组件和函数组件的所有核心区别
前端·javascript·react.js
️是782 小时前
信息奥赛一本通—编程启蒙(3345:【例60.2】 约瑟夫问题)
开发语言·c++·算法
大家的林语冰2 小时前
《前端周刊》React 败北,虾皇登基,OpenClaw 勇夺 GitHub 第一开源软件
前端·javascript·github
LSL666_2 小时前
IService——查询(下)
java·开发语言·数据库·mybatisplus·iservice
小码哥_常2 小时前
从0到1,解锁Android WebView混合开发新姿势
前端
早點睡3902 小时前
ReactNative项目鸿蒙化三方库集成实战:react-native-calendars(日历展开和日程模块存在兼容性问题)
react native·react.js·harmonyos
众创岛2 小时前
python中enumerate的用法
开发语言·python
533_2 小时前
[vue3] 动态引入本地静态资源(URL)
前端·javascript·vue.js
add45a2 小时前
C++中的智能指针详解
开发语言·c++·算法