持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情
前言
axios
是一个基于promise
的HTTP
库,可以用在浏览器
和node.js
中,在服务端它使用原生 node.js
的http
模块, 而在客户端 (浏览器) 则使用 XMLHttpRequests
主要功能有:
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换
JSON
数据 - 客户端支持防御
CSRF
/XSRF
创建项目
先使用vue-cli
创建一个新的项目,配置按照自己的需要选择,默认的也可
vue create vue_axios
cd vue_axios
npm run serve
基本使用
安装和引入
npm i axios -S
在Vue
项目中安装其他插件的时候,可以直接在 main.js
中引入并使用 Vue.use()
来注册,比如Echarts
、Vuex
等,但axios
并不是vue
插件,它跟jQuery
一样,只是一个工具库,所以只能在每个需要发送请求的组件中即时引入。
为了解决上面的问题,我们可以在引入axios
后,通过修改原型链,来在全局更方便的调用
// main.js
import axios from 'axios'
Vue.prototype.$http = axios
在 main.js
中添加了这两行代码之后,就能直接在组件中使用 this.$http
来调用axios
了。
axios
为提供了几种使用的语法:axios(config)
、axios(url[, config])
和诸如axios.get(url[, config])
的请求方法别名形式,可以根据自己的习惯选择,比如下面的两种写法是一样的效果:
// axios(config)
this.$http({
method: 'get',
url: '/user',
data: {
name: 'xiaoming',
info: '12'
}
})
// axios.get(url[, config])
this.$http.get({
url: '/user',
data: {
name: 'xiaoming',
info: '12'
}
})
GET请求
// 向具有指定ID的用户发出请求
this.$http.get('/user?ID=12345')
.then(function (res) {
console.log(res);
})
.catch(function (err) {
console.log(err);
});
// 也可以通过 params 对象传递参数
this.$http.get('/user', {
params: {
ID: 12345
}
})
.then(function (res) {
console.log(res);
})
.catch(function (errr) {
console.log(err);
});
POST请求
this.$http.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (res) {
console.log(res);
})
.catch(function (err) {
console.log(err);
});
并发请求
function getUserAccount() {
return this.$http.get('/user/12345');
}
function getUserPermissions() {
return this.$http.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(this.$http.spread(function (acct, perms) {
//两个请求现已完成
}));
二次封装
目的
- 将项目的配置逻辑添加到
axios
的请求中,来改变接口请求的地址 - 监听所有接口,在请求前和请求后进行拦截,如在请求前添加
header
,在请求后捕获catch
,对异常的http
状态进行处理 - 对外只暴露一个
request
接口,统一各种请求的代码
思路
在项目的src
目录下,本质上网络请求也是一个工具函数,所以新建一个utils
文件夹,然后在里面新建用于封装axios
的axios.js
文件和用于统一管理请求方法的data.js
文件。
axios 封装
项目环境可能有开发环境或生产环境。我们通过node
的环境变量来匹配我们的默认接口。
这里为了代码的功能分离,在src
下新建了config
文件夹来存放切换baseUrl
的文件。至此二次封装相关的项目目录如下:
在index.js
中,主要对生产环境和开发环境的basedUrl
进行了处理,可根据自己的需要进行发散:
// index.js
export default {
// 配置Ajax请求相关的 baseUrl
baseUrl: {
// 开发环境下用这个
dev: "/api",
// 生产环境下用这个
pro: "",
},
};
然后在axios.js
中使用:
// axios.js
import axios from "axios";
import config from "@/config/index.js";
// 根据判断当前环境配置 baseUrl
const baseUrl =
process.env.NODE_ENV === "development"
? config.baseUrl.dev
: config.baseUrl.pro;
由于我们只想对外暴露一个request
接口,所以在axios.js
中导出的是axios
实例,而在类中定义了所有的拦截器和请求逻辑:
// axios.js
class HttpRequest {
constructor(baseUrl) {
this.baseUrl = baseUrl;
}
// 定义axios的配置,用于创建axios实例
getInsideConfig() {
const config = {
baseUrl: this.baseUrl,
header: {},
};
return config;
}
// 定义axios的拦截器
interceptors(instance) {
// 添加请求拦截器
instance.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
instance.interceptors.response.use(
function (response) {
// 对响应数据做点什么
return response;
},
function (error) {
// 对响应错误做点什么
console.log(error);
return Promise.reject(error);
}
);
}
// 定义axios的请求函数,最终调用的是request
request(options) {
// 创建axios实例
const instance = axios.create();
// 获取axios的配置信息
options = { ...this.getInsideConfig(), ...options };
// 调用axios的拦截器
this.interceptors(instance);
// 返回接口请求的结果
return instance(options);
}
}
export default new HttpRequest(baseUrl);
请求方法的管理与使用
在data.js
中直接导入axios.js
即可得到axios
实例,在传入请求的配置信息后直接将方法导出
import axios from "./axios";
export const getMenu = (param) => {
return axios.request({
url: "/permisson/getMenu",
method: "post",
data: param,
});
};
之后就可以在组件中直接调用了
<script>
import { getHomeData } from "@/utils/data.js";
mounted(){
getHomeData().then((res) => {
...
})
}
</script>