需要理解的概念有:
https://cra.docschina.org/docs/proxying-api-requests-in-development
测试代理服务器项目:http://qn.chinavanes.com/test_proxy_server.zip
在package.json中追加如下配置
"proxy":"http://localhost:5000"
说明:
src/App.js
import React, { Component } from 'react';
import axios from 'axios';
class App extends Component {
render() {
// 解构赋值
return ;
}
componentDidMount() {
this.getData();
}
getData = () => {
axios.get('/students').then((res) => {
console.log(res);
});
};
}
export default App;
package.json
proxy不能是数组,只能是单一代理地址,不能代理多个。
{
"name": "hello-react",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"axios": "^0.21.1",
"nanoid": "^3.1.23",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/plugin-transform-runtime": "^7.14.2",
"@babel/preset-flow": "^7.13.13"
},
"proxy": "http://localhost:5000"
}
需要理解的概念有:
第一步:创建代理配置文件
在src下创建配置文件:src/setupProxy.js
编写setupProxy.js配置具体代理规则:
const proxy = require('http-proxy-middleware')
// 默认已经安装,不需要再安装
module.exports = function (app) {
app.use(
'/demo', //请求前缀,代理服务器只有遇到端口号后面带有/api的请求才会转发给服务器
proxy({
target: 'http://localhost:5000', //配置真正服务器的地址
changeOrigin: true, //该配置写不写无所谓
pathRewrite: {
'^/demo': '' },
})
);
app.use(
'/test', //请求前缀,代理服务器只有遇到端口号后面带有/api的请求才会转发给服务器
proxy({
target: 'http://localhost:5001', //配置真正服务器的地址
changeOrigin: true, //该配置写不写无所谓
pathRewrite: {
'^/test': '' },
})
);
};
说明:
src/App.js
import React, { Component } from 'react';
import axios from 'axios';
class App extends Component {
render() {
// 解构赋值
return ;
}
componentDidMount() {
this.getData();
}
getData = () => {
axios.get('/demo/students').then((res) => {
console.log(res);
});
};
}
export default App;
需要理解的概念有:
静态页面:http://qn.chinavanes.com/users_page.zip
src/App.js
import React, { Component } from 'react';
import Search from './components/Search';
import List from './components/List';
class App extends Component {
render() {
return (
);
}
}
export default App;
src/components/Search/index.js
import React, { Component } from 'react';
export default class Search extends Component {
render() {
return (
Search Github Users
);
}
}
src/components/List/index.js
import React, { Component } from 'react';
import './index.css';
export default class List extends Component {
render() {
return (
);
}
}
src/components/List/index.css
.album {
min-height: 50rem;
/* Can be removed; just added for demo purposes */
padding-top: 3rem;
padding-bottom: 3rem;
background-color: #f7f7f7;
}
.card {
float: left;
width: 33.333%;
padding: .75rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align: center;
}
.card>img {
margin-bottom: .75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
public/index.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>React Apptitle>
<link rel="stylesheet" href="./css/bootstrap.css">
head>
<body>
<div id="root">div>
body>
html>
需要理解的概念有:
src/components/Search/index.js
import React, { Component } from 'react';
import axios from 'axios';
export default class Search extends Component {
search = () => {
const {
keywordElement: { value: keyword },
} = this; // 解构+赋值别名
// 关键字可以尝试用`atguigu`
axios.get(`https://api.github.com/search/users?q=${keyword}`).then(
(res) => {
console.log(res);
},
(err) => {
console.log(err);
}
);
};
render() {
return (
搜索github用户
(this.keywordElement = c)}
type='text' placeholder='请输入搜索的用户名称' />
);
}
}
src/components/Search/index.js
import React, { Component } from 'react';
import axios from 'axios';
export default class Search extends Component {
keyword = React.createRef();
search = () => {
const {
current: { value: keyword },
} = this.keyword; // 解构+赋值别名
// 关键字可以尝试用`atguigu`
axios.get(`https://api.github.com/search/users?q=${keyword}`).then(
(res) => {
console.log(res);
},
(err) => {
console.log(err);
}
);
};
render() {
return (
搜索github用户
);
}
}
需要理解的概念有:
src/App.js
import React, { Component } from 'react';
import Search from './components/Search';
import List from './components/List';
class App extends Component {
state = { users: [] };
saveUsers = (users) => {
this.setState({ users });
};
render() {
const { users } = this.state;
return (
);
}
}
export default App;
src/components/Search/index.js
import React, { Component } from 'react';
import axios from 'axios';
export default class Search extends Component {
keyword = React.createRef();
search = () => {
const {
current: { value: keyword },
} = this.keyword; // 解构+赋值别名
// 关键字可以尝试用`atguigu`
axios.get(`https://api.github.com/search/users?q=${keyword}`).then(
(res) => {
console.log(res);
this.props.saveUsers(res.data.items);
},
(err) => {
console.log(err);
}
);
};
render() {
return (
搜索github用户
);
}
}
src/components/List/index.js
import React, { Component } from 'react';
import './index.css';
export default class List extends Component {
render() {
const { users } = this.props;
return (
);
}
}
需要理解的概念有:
src/App.js
import React, { Component } from 'react';
import Search from './components/Search';
import List from './components/List';
class App extends Component {
state = {
users: [],
isFirst: true, // 是否第一次打开
isLoading: false, // 是否显示isLoading
err: '', // 错误提示内容
};
updateAppState = (stateObj) => {
this.setState(stateObj);
};
render() {
return (
);
}
}
export default App;
src/components/Search/index.js
import React, { Component } from 'react';
import axios from 'axios';
export default class Search extends Component {
keyword = React.createRef();
search = () => {
const {
current: { value: keyword },
} = this.keyword; // 解构+赋值别名
// 发送请求前通知App更新状态
this.props.updateAppState({ isFirst: false, isLoading: true });
// 关键字可以尝试用`atguigu`
axios.get(`https://api.github.com/search/users?q=${keyword}`).then(
(res) => {
// 请求成功以后通知App更新状态
this.props.updateAppState({ isLoading: false,
users: res.data.items });
},
(err) => {
// 请求失败以后通知App更新状态
this.props.updateAppState({ isLoading: false, err: err });
}
);
};
render() {
return (
搜索github用户
);
}
}
src/components/List/index.js
import React, { Component } from 'react';
import './index.css';
export default class List extends Component {
render() {
const { isFirst, isLoading, err, users } = this.props;
return (
);
}
}
需要理解的概念有:
src/App.js
import React, { Component } from 'react';
import Search from './components/Search';
import List from './components/List';
class App extends Component {
render() {
return (
);
}
}
export default App;
src/components/Search/index.js
import React, { Component } from 'react';
import axios from 'axios';
import PubSub from 'pubsub-js';
export default class Search extends Component {
keyword = React.createRef();
search = () => {
const {
current: { value: keyword },
} = this.keyword; // 解构+赋值别名
// 发送请求前通知List更新状态
PubSub.publish('pubsubEvent', { isFirst: false, isLoading: true });
// 关键字可以尝试用`atguigu`
axios.get(`https://api.github.com/search/users?q=${keyword}`).then(
(res) => {
// 请求成功以后通知List更新状态
PubSub.publish('pubsubEvent', { isLoading: false, users: res.data.items });
},
(err) => {
// 请求失败以后通知List更新状态
PubSub.publish('pubsubEvent', { isLoading: false, err: err });
}
);
};
render() {
return (
搜索github用户
);
}
}
src/components/List/index.js
import React, { Component } from 'react';
import './index.css';
import PubSub from 'pubsub-js';
export default class List extends Component {
state = {
users: [],
isFirst: true, // 是否第一次打开
isLoading: false, // 是否显示isLoading
err: '', // 错误提示内容
};
componentDidMount() {
this.psEvent = PubSub.subscribe('pubsubEvent', (_, data) => {
this.setState(data);
});
}
componentWillUnmount() {
PubSub.unsubscribe(this.psEvent);
}
render() {
// this.props转成this.state
const { isFirst, isLoading, err, users } = this.state;
return (
);
}
}
需要理解的概念有:
1.jQuery ajax
$.ajax({
type: 'POST',
url: url,
data: data,
dataType: dataType,
success: function () {
},
error: function () {
}
});
优势与不足点:
2.axios
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
优势与不足点:
3.fetch
try {
let response = await fetch(url);
let data = response.json();
console.log(data);
} catch(e) {
console.log("Oops, error", e);
}
优势与不足点:
为什么要用axios?
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:
需要理解的概念有:
1.拆分静态组件,设计状态时要考虑全面,例如带有网络请求的组件,要考虑请求失败怎么办
2.分析得知:Search组件负责搜索,List组件负责展示,状态要交给App
3.List组件不仅要展示用户信息,还要展示:欢迎词、loading、错误信息
4.在App中设计一个方法:getSearchInfo去更新App的状态,一个一个写太麻烦
5.批量的给List组件传递参数:
6.在List中用三目运算符进行连续判断,从而决定List组件展示什么
7.先订阅,再发布(理解:有一种隔空对话的感觉)
8.适用于任意组件间通信
rror", e);
}
优势与不足点:
- 符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象里
- 更好更方便的写法
- 更加底层,提供的API丰富(request, response)
- 脱离了XHR,是ES规范里新的实现方式
1)fetchtch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
2)fetch默认不会带cookie,需要添加配置项
3)fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了量的浪费
4)fetch没有办法原生监测请求的进度,而XHR可以
**为什么要用axios?**
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:
- 从浏览器中创建 XMLHttpRequest
- 从 node.js 发出 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据客户端支持防止CSRF/XSRF
# 九 总结github搜索案例
需要理解的概念有:
1.拆分静态组件,设计状态时要考虑全面,例如带有网络请求的组件,要考虑请求失败怎么办
2.分析得知:Search组件负责搜索,List组件负责展示,状态要交给App
3.List组件不仅要展示用户信息,还要展示:欢迎词、loading、错误信息
4.在App中设计一个方法:getSearchInfo去更新App的状态,一个一个写太麻烦
5.批量的给List组件传递参数:`
`
6.在List中用三目运算符进行连续判断,从而决定List组件展示什么
7.先订阅,再发布(理解:有一种隔空对话的感觉)
8.适用于任意组件间通信
9.componentDidMount中订阅消息,要在组件的componentWillUnmount中进行取消订阅