axios:是对ajax进行了封装,可以实现异步请求
1、前后端分离:在前端中引入axios.js文件
2、模块开发:在项目中安装axios模块
axios中常用的方法:
GET请求:
方式一:
axios({
method: 'get', // 默认请求方式为get
url: 'api',
params: {
// 传递参数
key: value
},
headers: {
// 设置请求头信息
key: value
}
responseType: 'json'
}).then(response => {
// 请求成功
let res = response.data;
console.log(res);
}).catch(error => {
// 请求失败,
console.log(error);
});
方式二:
axios.get("api", {
params: {
// 传递参数
key: value
},
headers: {
// 设置请求头信息,可以传递空值
key: value
}
}).then(response => {
let res = response.data; // 请求成功
console.log(res);
}).catch(error => {
// 请求失败,
console.log(error);
});
POST请求
方式一:
// 注:post请求方法有的要求参数格式为formdata格式,此时需要借助 Qs.stringify()方法将对象转换为字符串
let obj = qs.stringify({
key: value
});
axios({
method: 'post',
url: 'api',
data: obj, // 传递参数
headers: {
// 设置请求头信息
key: value
}
responseType: 'json'
}).then(response => {
// 请求成功
let res = response.data;
console.log(res);
}).catch(error => {
// 请求失败,
console.log(error);
});
方式二:
let data = {
key: value},
let headers = {
USERID: "",
TOKEN: ""
};
// 若无headers信息时,可传空对象占用参数位置
axios.post("api", qs.stringify(data), {
headers
}).then(response => {
// 请求成功
let res = response.data;
console.log(res);
}).catch(error => {
// 请求失败
console.log(error);
});
Qs的使用:
引用cdn或者使用npm、cnpm或者yarn进行插件安装
使用cdn时,默认全局变量为Qs
Qs基本方法使用:
工具库: PubSubJS
下载: npm install pubsub-js --save
使用:
import PubSub from 'pubsub-js' //引入
PubSub.subscribe('delete', function(data){
}); //订阅
PubSub.publish('delete', data) //发布消息
fetch: 原生函数,不再使用XmlHttpRequest对象提交ajax请求
老版本浏览器可能不支持
GET请求:
fetch(url).then(function(response) {
return response.json()
}).then(function(data) {
console.log(data)
}).catch(function(e) {
console.log(e)
});
POST请求:
fetch(url, {
method: "POST",
body: JSON.stringify(data),
}).then(function(data) {
console.log(data)
}).catch(function(e) {
console.log(e)
})
1、使用axios方法:
index.html:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="stylesheet" href="./css/bootstrap.css">
<title>React Apptitle>
head>
<body>
<div id="root">div>
body>
html>
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
App.js:
import React, {
Component } from 'react'
import Search from './components/Search'
import List from './components/List'
export default class App extends Component {
state = {
//初始化状态
users:[], //users初始值为数组
isFirst:true, //是否为第一次打开页面
isLoading:false,//标识是否处于加载中
err:'',//存储请求相关的错误信息
}
//更新App的state
updateAppState = (stateObj)=>{
this.setState(stateObj)
}
render() {
return (
<div className="container">
<Search updateAppState={
this.updateAppState}/>
<List {
...this.state}/>
</div>
)
}
}
setupProxy.js(配置代理):
const proxy = require('http-proxy-middleware')
module.exports = function(app){
app.use(
proxy('/api1',{
//遇见/api1前缀的请求,就会触发该代理配置
target:'http://localhost:5000', //请求转发给谁
changeOrigin:true,//控制服务器收到的请求头中Host的值
pathRewrite:{
'^/api1':''} //重写请求路径(必须)
})
)
}
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%;
}
List目录下的index.jsx:
import React,{
Component} from "react";
import './index.css'
export default class List extends Component{
render() {
const {
users,isFirst,isLoading,err} = this.props
return (
<div className="row">
{
isFirst ? <h2>欢迎使用,输入关键字,随后点击搜索</h2> :
isLoading ? <h2>Loading......</h2> :
err ? <h2 style={
{
color:'red'}}>{
err}</h2> :
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>
)
}
}
Search目录下的index.jsx:
import React,{
Component} from "react";
import axios from 'axios';
export default class Search extends Component{
search=()=>{
//获取用户的输入 连续解构赋值+重命名
const {
keyWordElement:{
value:keyWord}}=this;
//发送请求前通知App更新状态
this.props.updateAppState({
isFirst: false,isLoading: true})
//发送网络请求
axios.get(`/api1/search/users?q=${
keyWord}`).then(
response=>{
this.props.updateAppState({
isLoading: false,users: response.data.items})
},
error=>{
this.props.updateAppState({
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>
)
}
}
服务器 server.js: 需要先启动服务器
const express = require("express")
const axios = require("axios")
const app = express()
/*
请求地址: http://localhost:3000/search/users?q=aa
后台路由
key: /search/users
value: function () {}
*/
app.get("/search/users", function (req, res) {
const {
q} = req.query
axios({
url: 'https://api.github.com/search/users',
params: {
q}
}).then(response => {
res.json(response.data)
})
})
app.listen(5000, "localhost", (err) => {
if (!err){
console.log("服务器启动成功")
console.log("请求github真实数据请访问:http://localhost:5000/search/users")
}
else console.log(err);
})
2、使用pubsub方法:
其余文件代码均不变
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>
)
}
}
List目录下的index.jsx:
import React,{
Component} from "react";
import PubSub from 'pubsub-js';
import './index.css'
export default class List extends Component{
state = {
//初始化状态
users:[], //users初始值为数组
isFirst:true, //是否为第一次打开页面
isLoading:false,//标识是否处于加载中
err:'',//存储请求相关的错误信息
}
componentDidMount() {
this.token=PubSub.subscribe('msg',(_,stateObj)=>{
this.setState(stateObj);
})
}
componentWillUnmount() {
PubSub.unsubscribe(this.token);
}
render() {
const {
users,isFirst,isLoading,err} = this.state
return (
<div className="row">
{
isFirst ? <h2>欢迎使用,输入关键字,随后点击搜索</h2> :
isLoading ? <h2>Loading......</h2> :
err ? <h2 style={
{
color:'red'}}>{
err}</h2> :
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>
)
}
}
Search目录下的index.jsx:
import React,{
Component} from "react";
import PubSub from 'pubsub-js';
import axios from 'axios';
export default class Search extends Component{
search=()=>{
//获取用户的输入 连续解构赋值+重命名
const {
keyWordElement:{
value:keyWord}}=this;
//发送请求前通知List更新状态
// this.props.updateAppState({isFirst: false,isLoading: true})
PubSub.publish('msg',{
isFirst: false,isLoading: true})
//发送网络请求
axios.get(`/api1/search/users?q=${
keyWord}`).then(
response=>{
// this.props.updateAppState({isLoading: false,users: response.data.items})
PubSub.publish('msg',{
isLoading: false,users: response.data.items})
},
error=>{
// this.props.updateAppState({isLoading: false,err:error.message})
PubSub.publish('msg',{
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>
)
}
}
3、使用fetch方法:
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>
)
}
}
List目录下的index.jsx:
import React,{
Component} from "react";
import PubSub from 'pubsub-js';
import './index.css'
export default class List extends Component{
state = {
//初始化状态
users:[], //users初始值为数组
isFirst:true, //是否为第一次打开页面
isLoading:false,//标识是否处于加载中
err:'',//存储请求相关的错误信息
}
componentDidMount() {
this.token=PubSub.subscribe('msg',(_,stateObj)=>{
this.setState(stateObj);
})
}
componentWillUnmount() {
PubSub.unsubscribe(this.token);
}
render() {
const {
users,isFirst,isLoading,err} = this.state
return (
<div className="row">
{
isFirst ? <h2>欢迎使用,输入关键字,随后点击搜索</h2> :
isLoading ? <h2>Loading......</h2> :
err ? <h2 style={
{
color:'red'}}>{
err}</h2> :
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>
)
}
}
Search目录下的index.js:
import React,{
Component} from "react";
import PubSub from 'pubsub-js';
// import axios from 'axios';
export default class Search extends Component{
search=async ()=> {
//获取用户的输入 连续解构赋值+重命名
const {
keyWordElement: {
value: keyWord}} = this;
//发送请求前通知List更新状态
// this.props.updateAppState({isFirst: false,isLoading: true})
PubSub.publish('msg', {
isFirst: false, isLoading: true})
//发送网络请求
// axios.get(`/api1/search/users?q=${keyWord}`).then(
// response=>{
// // this.props.updateAppState({isLoading: false,users: response.data.items})
// PubSub.publish('msg',{isLoading: false,users: response.data.items})
// },
// error=>{
// // this.props.updateAppState({isLoading: false,err:error.message})
// PubSub.publish('msg',{isLoading: false,err:error.message})
// }
// )
try{
const response = await fetch(`/api1/search/users?q=${
keyWord}`)
const data = await response.json()
PubSub.publish('msg', {
isFirst: false, users:data.items})
}catch (error){
PubSub.publish('msg', {
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>
)
}
}
案例相关知识点:
设计状态时要考虑全面,例如带有网络请求的组件,要考虑请求失败怎么办
ES6小知识点:解构赋值+重命名
let obj = {
a:{
b:1}}
const {
a} = obj; //传统解构赋值
const {
a:{
b}} = obj; //连续解构赋值
const {
a:{
b:value}} = obj; //连续解构赋值+重命名
消息订阅与发布机制(pubsub)
fetch发送请求(关注分离的设计思想)
try {
const response= await fetch(`/api1/search/users2?q=${
keyWord}`)
const data = await response.json()
console.log(data);
} catch (error) {
console.log('请求出错',error);
}