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"),
);
相关推荐
萑澈3 小时前
Windows 7 运行 Electron 安装包报“不是有效的 Win32 应用程序”怎么办
javascript·windows·electron
W.A委员会3 小时前
JS原型链详解
开发语言·javascript·原型模式
止语Lab3 小时前
Go并发编程实战:Channel 还是 Mutex?一个场景驱动的选择框架
开发语言·后端·golang
懂懂tty4 小时前
React状态更新流程
前端·react.js
小码哥_常4 小时前
告别繁琐!手把手教你封装超实用Android原生Adapter基类
前端
她说彩礼65万4 小时前
C# 实现简单的日志打印
开发语言·javascript·c#
绿浪19844 小时前
c# 中结构体 的定义字符串字段(性能优化)
开发语言·c#
skywalk81634 小时前
pytest测试的时候这是什么意思?Migrating <class ‘kotti.resources.File‘>
前端·python
房开民4 小时前
可变参数模板
java·开发语言·算法
一只蝉nahc4 小时前
vue使用iframe内嵌unity模型,并且向模型传递信息,接受信息
前端·vue.js·unity