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"),
);
相关推荐
Csvn6 小时前
OpenSpec 详细使用教程
前端
方也_arkling6 小时前
【Java-Day08】static / final / 枚举
java·开发语言
风吹夏回6 小时前
Python 全局异常处理:从“满屏 try-except”到优雅兜底
开发语言·python
Chengbei116 小时前
一站式源码安全检测工具、云安全 / APP / 小程序源码敏感信息递归多层目录扫描AK、JWT、手机号、身份证等敏感信息
java·开发语言·安全·web安全·网络安全·系统安全·安全架构
llz_1126 小时前
web-第一次课后作业
java·开发语言·idea
小熊Coding6 小时前
Python爬取当当网二手图书项目实战!
开发语言·爬虫·python·beautifulsoup·requests·二手图书
之歆6 小时前
Day19_LESS 完全指南——从入门到工程实践
前端·css·less
秋96 小时前
Java项目运行5天左右自动宕机:系统性定位与解决方案
java·开发语言·python
xiaoshuaishuai87 小时前
C# 内存管理与资源泄漏
开发语言·c#
云水一下7 小时前
HTML5 从入门到精通:实战收官——从零搭建完整静态网站,综合运用所有知识
前端·html5