Vue学习-axios

前言

本文将介绍axios的相关操作。

相关的后端服务器是用Flask搭建的,仅用于演示:

web.py

1
2
3
4
5
6
7
8
9
10
from flask import Flask,request
from flask_cors import CORS #引入CORS库

app = Flask(__name__)
CORS(app, supports_credentials=True) #用于解决跨域问题

@app.route("/")

if __name__=="__main__":
app.run()

说明:引入CORS库用于解决跨域问题。

以下的axios网络请求的代码都在Vue项目src文件夹下的main.js中完成。

这里也介绍一个网站,可以用于网络请求的测试:httpbin.org


axios

介绍

以下内容来自官网:axios中文文档|axios中文网 | axios (axios-js.com)

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

特性:

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

支持多种请求方式:

  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.options(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])

基本使用

配置axios

打开终端,进入项目根目录,键入如下命令(注意版本号):

1
npm install axios --save

导入

在使用的文件头中导入:

1
import axios from 'axios'

发送GET/POST请求

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import Vue from 'vue'
import App from './App'
import axios from 'axios'

Vue.config.productionTip = false

new Vue({
el: '#app',
render: h => h(App)
})


axios({
url: 'http://127.0.0.1:5000',
method: 'post',
params: {
name: 'HuaZhu',
age: 18
}
}).then((res) => {
console.log(res);
})

说明:

(类似于ajax的使用方式)

axios的参数需要传入一个对象,该对象有以下属性:

  • url:用于指定请求的URL
  • method:用于指定请求方式(getpost),不写该参数默认使用get方式
  • params:用于附带参数信息

值得注意的是axios已集成Promise,在发送请求后会自动执行resolve()函数,因此可以在后面直接链接then()函数,用于接收请求返回值。

web.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from flask import Flask,request
from flask_cors import CORS

app = Flask(__name__)
CORS(app, supports_credentials=True)

@app.route("/",methods=["GET","POST"])
def test():
if request.method=="GET":
name = request.args.get("name")
age = request.args.get("age")
print(name,age)
return "get请求已收到"
elif request.method=="POST":
name = request.values.get("name")
age = request.values.get("age")
print(name,age)
return "post请求已收到"
else:
return "网络请求方式不正确"

if __name__=="__main__":
app.run()

效果展示:

发送并发请求

如果需要向服务器同时发送多个并发请求,并取回每个请求的结果,然后对这些返回结果操作。axios提供了axios.all()方法,使用格式如下:

axios.all([axios(), axios()], ...).then((results) => {...})

说明:

  • axios.all()的参数为列表,里面可以写任意个axios()方法
  • 最后then()获得的返回值同为列表形式,里面存放了每一个请求的结果

现在假设要向服务器同时发送get和post请求,并拿到返回值:

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import Vue from 'vue'
import App from './App'

import axios from 'axios'

Vue.config.productionTip = false

new Vue({
el: '#app',
render: h => h(App)
})

axios.all([axios({
url: 'http://127.0.0.1:5000',
method: 'get', //发送get请求
params: {
name: 'HuaZhu',
age: 18
}
}), axios({
url: 'http://127.0.0.1:5000',
method: 'post', //发送post请求
params: {
name: 'HuaZhu',
age: 18
}
})]).then(results => {
console.log(results)
})

web.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from flask import Flask,request
from flask_cors import CORS

app = Flask(__name__)
CORS(app, supports_credentials=True)

@app.route("/",methods=["GET","POST"])
def test():
if request.method=="GET":
name = request.args.get("name")
age = request.args.get("age")
print(name,age)
return "get请求已收到"
elif request.method=="POST":
name = request.values.get("name")
age = request.values.get("age")
print(name,age)
return "post请求已收到"
else:
return "网络请求方式不正确"

if __name__=="__main__":
app.run()

效果展示:

返回结果列表拿到,如果要详细访问,可以通过列表的index下标值。但是axios还提供了axios.spread()方法可以直接拆分返回结果列表,拿到具体的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
axios.all([axios({
url: 'http://127.0.0.1:5000',
method: 'get',
params: {
name: 'HuaZhu',
age: 18
}
}), axios({
url: 'http://127.0.0.1:5000',
method: 'post',
params: {
name: 'HuaZhu',
age: 18
}
})]).then(axios.spread((res1, res2) => {
console.log(res1);
console.log(res2);
}))

效果如下:

配置信息

基本配置

可以在axios对象中添加诸如baseURLtimeout等的配置信息:

1
2
3
4
5
6
7
8
9
10
11
12
axios({
baseURL: 'http://127.0.0.1:5000',
url: '/home',
timeout: 5000, //单位ms
method: 'post',
params: {
name: 'HuaZhu',
age: 18
}
}).then((res) => {
console.log(res);
})

全局配置

如果想在多个请求中使用同一配置,可以将这些配置信息抽离出来,设置全局默认配置:axios.defaults.xxx

1
2
3
4
5
6
7
8
9
10
11
12
13
axios.defaults.baseURL = 'http://127.0.0.1:5000'
axios.defaults.timeout = 5000

axios({
url: '/home',
method: 'post',
params: {
name: 'HuaZhu',
age: 18
}
}).then((res) => {
console.log(res);
})

axios实例

全局默认配置在项目规模较小的情况下(请求配置基本一致)可以使用,一旦涉及到的请求量增加,面临的情况可能是一类请求需要一种配置,另一类请求需要另外一种配置,如果这时再设置全局默认配置就不是很合适了。为此可以使用axios实例:axios.create()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const instance1 = axios.create({  //创建axios实例一
baseURL: 'http://127.0.0.1:5000',
timeout: 5000
})

instance1({ //使用axios实例一
url: '/home',
method: 'get',
}).then((res) => {
console.log(res);
})

instance1({ //使用axios实例一
url: '/about',
method: 'post',
}).then((res) => {
console.log(res);
})

const instance2 = axios.create({ //创建axios实例二
baseURL: 'http://127.0.0.1:8080',
timeout: 10000
})

instance2({ //使用axios实例二
url: '/home',
method: 'get',
}).then((res) => {
console.log(res);
})

instance2({ //使用axios实例二
url: '/about',
method: 'post',
}).then((res) => {
console.log(res);
})

常见的配置信息:

配置信息 格式
请求地址 url: ‘/home’
请求类型 method: ‘get’
请求根路径 baseURL: ‘http://127.0.0.1:5000
请求前的数据处理 transformRequest:[function(data){}]
请求后的数据处理 transformResponse: [function(data){}]
自定义的请求头 headers:{‘x-Requested-With’:‘XMLHttpRequest’}
URL查询对象 params:{ name: ‘HuaZhu’, age: 18 }
查询对象序列化函数 paramsSerializer: function(params){ }
request body data: { key: ‘a’}
超时设置(ms) timeout: 1000
跨域是否带Token withCredentials: false
自定义请求处理 adapter: function(resolve, reject, config){}
身份验证信息 auth: { uname: ‘’, pwd: ‘12’}
响应的数据格式 json / blob /document /arraybuffer / text / stream responseType: ‘json’

axios封装

在大型项目中,往往第三方库在大量使用的情况下最好进行封装,在调用的时候只使用自己封装的内容就好。原因:如果第三方库停止维护,方便改用其他的代替内容。修改起来仅需改动封装的部分代码就好。

在项目的src文件夹下新建一个network文件夹,用于存放网络相关的封装代码。在其中新建名为axios-request.js的文件:

1
2
3
4
5
6
7
8
9
10
11
12
import axios from 'axios'

export function axios_request(config) {
// 创建axios实例
const instance = axios.create({
baseURL: 'http://127.0.0.1:5000',
timeout: 5000
})

// 发送网络请求
return instance(config)
}

假设未来决定不再使用axios,改用其他的第三方库,如果该库也自动集成Promise,那调用格式同上,如果没有,那么就需要手动返回一个Promise对象:

1
2
3
4
5
6
7
8
import xxx_request from 'xxx'

export function xxx_request(config) {
return new Promise((resolve, reject) => {
// 1.调用xxx第三方库
// 2.发送请求
})
}

在其他文件中就可以直接调用封装的axios_request(config)函数,其中config就是发送请求的配置信息:

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import Vue from 'vue'
import App from './App'

import {axios_request} from './network/axios-request' //导入封装函数

Vue.config.productionTip = false

new Vue({
el: '#app',
render: h => h(App)
})

axios_request({ //使用封装函数
url: '/home',
method: 'post',
params: {
name: 'HuaZhu',
age: 18
}
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
})

说明:

由于axios.create()实例对象集成Promise,在调用时会自动执行resolve()函数,因而可以在使用封装函数后直接调用then()catch()函数。

web.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from flask import Flask,request
from flask_cors import CORS

app = Flask(__name__)
CORS(app, supports_credentials=True)

@app.route("/home",methods=["GET","POST"])
def test():
if request.method=="GET":
name = request.args.get("name")
age = request.args.get("age")
print(name,age)
return "get请求已收到"
elif request.method=="POST":
name = request.values.get("name")
age = request.values.get("age")
print(name,age)
return "post请求已收到"
else:
return "网络请求方式不正确"

if __name__=="__main__":
app.run()

拦截器

axios提供了拦截器,用于在发送每次请求或者从服务器得到返回结果时,进行相应的处理。

请求拦截

作用:

  • 当发送网络请求时,在页面中添加一个loading组件,作为加载动画
  • 某些请求要求用户必须登录,判断用户是否有token(令牌),如果没有则跳转到login页面
  • 对请求的参数进行序列化

格式:

局部拦截器:instance.interceptors.request.use(onFulfilled(), onRejected())

全局拦截器:axios.interceptors.request.use(onFulfilled(), onRejected())

axios-request.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import axios from 'axios'

export function axios_request(config) {
// 创建axios实例
const instance = axios.create({
baseURL: 'http://127.0.0.1:5000',
timeout: 5000
})

// 请求拦截器
instance.interceptors.request.use(config => {
console.log('成功拦截到请求');
console.log(config.params) //拦截成功后可以在此对config请求执行操作
return config //最后需要把拦截结果释放
}, err => {
console.log('拦截请求失败');
return err
})

// 发送网络请求
return instance(config)
}

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import Vue from 'vue'
import App from './App'

import {axios_request} from './network/axios-request'

Vue.config.productionTip = false

new Vue({
el: '#app',
render: h => h(App)
})

axios_request({
url: '/home',
method: 'post',
params: {
name: 'HuaZhu',
age: 18
}
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
})

web.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from flask import Flask,request
from flask_cors import CORS

app = Flask(__name__)
CORS(app, supports_credentials=True)

@app.route("/home",methods=["GET","POST"])
def test():
if request.method=="GET":
name = request.args.get("name")
age = request.args.get("age")
print(name,age)
return "get请求已收到"
elif request.method=="POST":
name = request.values.get("name")
age = request.values.get("age")
print(name,age)
return "post请求已收到"
else:
return "网络请求方式不正确"

if __name__=="__main__":
app.run()

效果展示:

返回结果拦截

作用:

  • 主要是对返回的结果进行过滤
  • 相应失败后根据错误信息做出不同的响应

格式:

局部拦截器:instance.interceptors.response.use(onFulfilled(), onRejected())

全局拦截器:axios.interceptors.response.use(onFulfilled(), onRejected())

axios-request.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import axios from 'axios'

export function axios_request(config) {
// 创建axios实例
const instance = axios.create({
baseURL: 'http://127.0.0.1:5000',
timeout: 5000
})

// 响应拦截器
instance.interceptors.response.use(response => {
console.log('成功拦截到响应');
console.log(response) //拦截成功后可以在此对response响应执行操作
return response.data //最后需要把拦截结果释放
}, err => {
console.log('拦截响应失败');
return err
})

// 发送网络请求
return instance(config)
}

效果展示:


后记

要在项目实战中多运用练习以加深印象。