一、路由样式丢失问题
1、问题复现
(1)html
- public/index.html
html
...
<link rel="stylesheet" href="./css/myStyle.css">
...
- 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
- About 页面
js
import React, { Component } from "react";
export default class About extends Component {
render() {
return <h3 className="my-box">About Content</h3>;
}
}
- Home 页面
js
import React, { Component } from "react";
export default class Home extends Component {
render() {
return <h3 className="my-box">Home Content</h3>;
}
}
(4)main
- 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>
);
}
}
- 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
-
访问
http://localhost:3000,样式生效此时请求样式的路径为
-
访问
http://localhost:3000/test/about,样式丢失此时请求样式的路径为
2、处理策略
- 使用
%PUBLIC_URL%环境变量
html
<link rel="stylesheet" href="%PUBLIC_URL%/css/myStyle.css">
3、访问路径小结
-
http://localhost:3000相当于 public 目录 -
可以指定路径以访问 public 目录下的文件,例如,
http://localhost:3000/favicon.ico,会返回 public 目录下的 favicon.ico 文件 -
如果没有指定路径,或者指定一个不存在的路径,默认会返回 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>
);
}
}
-
访问
http://localhost:3000,访问正常 -
访问
http://localhost:3000/about,访问正常 -
访问
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>
);
}
}
-
访问
http://localhost:3000,访问正常 -
访问
http://localhost:3000/about,跳转到http://localhost:3000 -
访问
http://localhost:3000/home,跳转到http://localhost:3000
(2)小结
-
多个 Route 可以同时匹配
-
访问
/about时,先匹配到<Route path="/about">,继续匹配到错误的<Redirect path="/about">,React Router 可能将其解析为某种重定向逻辑 -
访问
/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>
);
}
}
-
访问
http://localhost:3000,访问正常 -
访问
http://localhost:3000/about,访问正常 -
访问
http://localhost:3000/home,访问正常
(2)小结
-
Switch 只渲染第一个匹配到的组件
-
访问
/about时,第一个匹配的是<Route path="/about">,渲染 About 后就停止了,错误的 Redirect 没有被处理 -
访问
/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>
);
}
}
-
访问
http://localhost:3000,跳转到http://localhost:3000/about -
访问
http://localhost:3000/about,访问正常 -
访问
http://localhost:3000/home,跳转到http://localhost:3000/about
(2)小结
-
多个 Route 可以同时匹配
-
访问
/about时,先匹配到<Route path="/about">,继续匹配<Redirect to="/about" /> -
访问
/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>
);
}
}
-
访问
http://localhost:3000,跳转到http://localhost:3000/about -
访问
http://localhost:3000/about,访问正常 -
访问
http://localhost:3000/home,访问正常
(2)小结
-
Switch 只渲染第一个匹配到的组件
-
访问
/about时,第一个匹配的是<Route path="/about">,渲染 About 后就停止了 -
访问
/home时,第一个匹配的是<Route path="/home">,渲染 Home 后就停止了
三、路由传递参数
1、基本介绍
-
params 参数:适合传递必须参数,例如,ID、用户名等
-
search 参数:适合可选参数、过滤条件等
-
state 参数:适合传递复杂数据、敏感信息,不会显示在 URL 中
2、演示
(1)page
- 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>
);
}
}
- 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>
);
}
}
- 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>
);
}
}
- 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
- 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>
);
}
}
- 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"),
);