一、React 配置代理
1、在 package.json 文件中配置代理
(1)具体实现
- package.json
json
"proxy": "http://localhost:5000"
- App.jsx
js
import React, { Component } from "react";
import axios from "axios";
export default class App extends Component {
getStudentData = () => {
axios.get("/students").then(
(response) => {
console.log("成功了", response.data);
},
(error) => {
console.log("失败了", error);
},
);
};
render() {
return (
<div>
<button onClick={this.getStudentData}>点我获取学生数据</button>
</div>
);
}
}
(2)小结
- 工作方式:当请求了 3000 不存在的资源时,那么该请求会转发给5000(优先匹配前端资源)
-
优点:配置简单,前端请求资源时可以不加任何前缀
-
缺点:不能配置多个代理
2、在 setupProxy.js 文件中配置代理
(1)具体实现
- 在 src 目录下创建并配置 setupProxy.js 文件
js
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
createProxyMiddleware("/api1", {
target: "http://localhost:5000",
changeOrigin: true,
pathRewrite: { "^/api1": "" },
}),
createProxyMiddleware("/api2", {
target: "http://localhost:5001",
changeOrigin: true,
pathRewrite: { "^/api2": "" },
}),
);
};
- App.jsx
js
import React, { Component } from "react";
import axios from "axios";
export default class App extends Component {
getStudentData = () => {
axios.get("http://localhost:3000/api1/students").then(
(response) => {
console.log("成功了", response.data);
},
(error) => {
console.log("失败了", error);
},
);
};
getCarData = () => {
axios.get("http://localhost:3000/api2/cars").then(
(response) => {
console.log("成功了", response.data);
},
(error) => {
console.log("失败了", error);
},
);
};
render() {
return (
<div>
<button onClick={this.getStudentData}>点我获取学生数据</button>
<button onClick={this.getCarData}>点我获取汽车数据</button>
</div>
);
}
}
(2)解读
/api1是需要转发的请求,target 是转发目标地址,所有带有/api1前缀的请求都会转发给 target
js
createProxyMiddleware("/api1", {
target: "http://localhost:5000",
...
})
-
控制服务器接收到的请求头中 Host 字段的值,changeOrigin 默认值为 false,但我们一般设置为 true
-
changeOrigin 设置为 true 时,服务器收到的请求头中的 Host 字段为:localhost:5000
-
changeOrigin 设置为 false 时,服务器收到的请求头中的 Host 字段为:localhost:3000
-
js
changeOrigin: true,
- 去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
js
pathRewrite: { "^/api2": "" },
(3)小结
-
优点:可以配置多个代理,可以灵活的控制请求是否走代理
-
缺点:配置繁琐,前端请求资源时必须加前缀
二、搜索案例(Fetch + PubSub)
- List 组件
js
import React, { Component } from "react";
import PubSub from "pubsub-js";
import "./index.css";
export default class List extends Component {
state = {
users: [],
isFirst: true,
isLoading: false,
err: "",
};
componentDidMount() {
this.token = PubSub.subscribe("test", (msgName, stateObj) => {
this.setState(stateObj);
});
}
componentWillUnmount() {
PubSub.unsubscribe(this.token);
}
render() {
const { users, isFirst, isLoading, err } = this.state;
return (
<div className="row">
{isFirst ? (
<h3>欢迎使用,输入关键字,随后点击搜索</h3>
) : isLoading ? (
<h3>Loading...</h3>
) : err ? (
<h3 style={{ color: "red" }}>{err}</h3>
) : (
users.map((userObj) => {
return (
<div key={userObj.id} className="card">
<a rel="noreferrer" href={userObj.html_url} target="_blank">
<img alt="head_portrait" src={userObj.avatar_url} style={{ width: "100px" }} />
</a>
<p className="card-text">{userObj.login}</p>
</div>
);
})
)}
</div>
);
}
}
css
.album {
min-height: 50rem;
padding-top: 3rem;
padding-bottom: 3rem;
background-color: #f7f7f7;
}
.card {
float: left;
width: 33.333%;
padding: 0.75rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align: center;
}
.card > img {
margin-bottom: 0.75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
- Search 组件
js
import React, { Component } from "react";
import PubSub from "pubsub-js";
export default class Search extends Component {
search = async () => {
// 获取用户的输入(连续解构赋值 + 重命名)
const {
keyWordElement: { value: keyWord },
} = this;
// 发送请求前通知更新状态
PubSub.publish("test", { isFirst: false, isLoading: true });
try {
const response = await fetch(`/api1/search/users?q=${keyWord}`);
const data = await response.json();
// 请求成功后通知更新状态
PubSub.publish("test", { isLoading: false, users: data.items });
} catch (error) {
// 请求失败后通知更新状态
PubSub.publish("test", { isLoading: false, err: error.message });
}
};
render() {
return (
<section className="jumbotron">
<h3 className="jumbotron-heading"> 搜索 GitHub 用户</h3>
<div>
<input ref={(c) => (this.keyWordElement = c)} type="text" placeholder="输入关键词点击搜索" />
<button onClick={this.search}>搜索</button>
</div>
</section>
);
}
}
- App 组件
js
import React, { Component } from "react";
import Search from "./components/Search";
import List from "./components/List";
export default class App extends Component {
render() {
return (
<div className="container">
<Search />
<List />
</div>
);
}
}
- index.js
js
import React from "react"; // 引入 React 核心库
import ReactDOM from "react-dom"; // 引入 ReactDOM
import App from "./App"; // 引入 App 组件
// 渲染 App 组件到页面
ReactDOM.render(<App />, document.getElementById("root"));
- setupProxy.js
js
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
createProxyMiddleware("/api1", {
target: "http://localhost:5000",
changeOrigin: true,
pathRewrite: { "^/api1": "" },
}),
);
};
三、React 路由基本使用
- About 组件
js
import React, { Component } from "react";
export default class About extends Component {
render() {
return <h3>About Content</h3>;
}
}
- Home 组件
js
import React, { Component } from "react";
export default class Home extends Component {
render() {
return <h3>Home Content</h3>;
}
}
- App 组件
js
import React, { Component } from "react";
import { Link, Route } from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
export default class App extends Component {
render() {
return (
<div>
<h2>React Router Demo</h2>
<div>
<Link to="/about">About</Link>
<Link to="/home">Home</Link>
</div>
<div>
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
</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"),
);
四、NavLink
1、基本介绍
-
Link:单纯的页面跳转组件,提供导航功能
-
NavLink:是 Link 的特殊版本,除了导航功能,它会自动给当前激活的链接添加样式或类名
- NavLink 的 activeClassName 用于自定义激活类名,默认是 active
2、基本使用
- About 组件
js
import React, { Component } from "react";
export default class About extends Component {
render() {
return <h3>About Content</h3>;
}
}
- Home 组件
js
import React, { Component } from "react";
export default class Home extends Component {
render() {
return <h3>Home Content</h3>;
}
}
- App 组件
js
import React, { Component } from "react";
import { NavLink, Route } from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import "./App.css";
export default class App extends Component {
render() {
return (
<div>
<h2>React Router Demo</h2>
<div>
<NavLink activeClassName="selected" className="list-group-item" to="/about">
About
</NavLink>
<NavLink activeClassName="selected" className="list-group-item" to="/home">
Home
</NavLink>
</div>
<div>
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
</div>
</div>
);
}
}
css
.active {
color: red;
font-weight: bold;
background-color: #f0f0f0;
}
.selected {
color: blue;
font-weight: bold;
background-color: #f0f0f0;
}
- 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、NavLink 封装
(1)pages
- About 组件
js
import React, { Component } from "react";
export default class About extends Component {
render() {
return <h3>About Content</h3>;
}
}
- Home 组件
js
import React, { Component } from "react";
export default class Home extends Component {
render() {
return <h3>Home Content</h3>;
}
}
(2)components
- 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)main
- App 组件
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>
);
}
}
- 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"),
);