在 Vue 项目中,若想通过网络去请求一些数据,就需要使用 Axios 啦。
什么是 Axios?
Axios 是一个开源的可以用在客户端和 NodeJS 的异步通信框架,它的主要作用就是实现 Ajax 异步通信,其功能特点如下:
- 从浏览器中创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防御 XSRF(跨站请求伪造)
为什么使用 Axios?
由于 Vue 是一个视图层框架且严格准守SoC(关注度分离原则),所以它并不包含 Ajax 的通信功能。
为了解决通信问题,需要引入 Axios 框架。
Axios 框架的使用
基本使用
Axios 和 Ajax 很像,下面为一个案例: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
38
39
40
41
42
43
44
45
46
47
48// 发送 POST 请求
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
},
responseType:'stream'
});
// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 另一种指定参数的方式
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
// 携带数据
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
上面通过向 Axios 传递相关配置来创建请求,你应该可以很容易的看懂它们,其中:
method:请求方式,如 GET、POST、PUTurl:请求的 URL 路径responseType:指定返回的类型;then:数据成功返回时执行的函数,可以通过response.data取得数据;catch:数据返回失败时执行的函数,可以通过error指定错误信息。
别名
为方便起见,请求方法还提供了别名(部分):
axios.request(config)axios.get(url[, config])axios.post(url[, data[, config]])axios.put(url[, data[, config]])- …
拦截器
Axios 提供了拦截器,使得我们可以在以下操作过程中进行一些操作:
- 请求成功时
- 请求失败时
- 响应成功时
- 响应失败时
请求拦截
1 | // config 为 axios 配置中的信息 |
请求成功时可以进行如下操作:
- 过滤 config 中一些不符合服务器要求的信息
- 每次发送网络请求时在在界面显示一个请求的图标(动画)
- 监测 token 失效跳转到登录页要求用户重新登录
响应拦截(了解)
1 | axios.interceptors.response.use(res => { |
Vue 中 Axios 的安装与使用
首先执行如下命令安装:1
npm install axios --save
之后在需要的js文件导入即可使用:1
import axios from 'axios'
低级使用
对下面接口为http://127.0.0.1/user/query获取的 JSON 数据:1
2
3
4
5
6
7{
"id": 1,
"username": "jack",
"password": "123",
"name": "王五",
"telephone": 110
}
现在通过 Axios 获取到 Vue 页面中: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<div id="app">
{{info.id}}, {{info.username}}, {{info.password}}, {{info.name}}, {{info.telephone}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const vm = new Vue({
el: "#app",
data() {
return {
info: {
id: '',
username: '',
password: '',
name: '',
telephone: '',
}
}
},
created() {
axios({
method: 'get',
url: 'http://127.0.0.1/user/query',
})
.then(response => this.info = response.data);
}
});
</script>
页面输出结果:1
1, jack, 123, 王五, 110
高级使用
参数抽取
从前面的栗子中,我们会发现一个问题:很多参数是固定的(如接口的请求地址)。
在实际开发中,我们会一般利用 axios 的全局配置做一些抽取,:1
2
3
4
5
6// 基础 URL
axios.defaults.baseURL = 'http://www.lovike.cn/vue/api'
// 超时时间
axios.defaults.timeout = 50000
// 请求头
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
但是,有时候在同一项目中,由于服务器压力会设置多台,这时候使用全局的 URL 就不太合适了。
这时候,我们可以创建多个 axios 实例来解决这个问题:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21const first_instance = axios.create({
baseURL = 'http://www.lovike.cn/vue/api'
// 超时时间
timeout = 50000
})
const second_instance = axios.create({
baseURL = 'http://www.dreamsky.cn/vue/api'
// 超时时间
timeout = 40000
})
first_instance({
url: '/home'
}).then( res => {})
second_instance({
url: '/user/list',
params: {
}
}).then( res => {})
解耦
考虑这样一个问题:若 axios 不维护了或出现重大 bug 啦,此时项目需要更换网络请求模块。
你会发现,由于导入了太多的硬编码模块,需要全部修改,费时费力。
那么,为什么不在一开始的时候就考虑好扩展性,编写工具类封装 axios,然后在需要使用的时候导入并使用该工具类呢?
因此,我们可以在 vue 项目中创建一个专门的文件夹存放网络请求模块的文件utils,在其中编写工具类request.js:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import axios from 'axios'
export function request(config) {
return new Promise((resolve,reject) => {
// 创建 axios 实例
const instance = axios.create({
baseURL: 'http://lovike.cn/vue/api',
timeout: 5000
})
// 发送真正的网络请求
instance(config)
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
})
}
其可以简写如下哦:1
2
3
4
5
6
7
8
9
10
11
12import axios from 'axios'
export function request(config) {
// 创建 axios 实例
const instance = axios.create({
baseURL: 'http://lovike.cn/vue/api',
timeout: 5000
})
// 发送真正的网络请求
return instance(config)
}
其他地方这么导入使用就好了:1
2
3
4
5
6
7
8
9
10import {request} from './utils/request'
request({
method:
url: ''
}).then(res => {
}).catch(err => {
})