推荐使用Vue-cli工具来创建和管理项目,就算刚开始不熟悉,用着用着便可知晓其中的奥妙。前一段时间官方所推荐的数据请求插件还是Vue-resource
,但现在已经变了,变成了Axios
,不用知道为什么变了,反正这个用起来比那个好一些,用就是了,下面是一些封装axios
请求的一些经验,不对之处,还望多多指教!
01
创建文件,Vue项目初始化之后,在src
目录下再创建一个util
工具文件夹,一般就是用来存放一些封装的函数方法,现在让我们在util
文件目录下创建一个http.js
文件,封装axios
方法。
02
直接上代码(常规版),代码中有详细的注释
import axios from 'axios' //引用axios
import {Promise} from 'es6-promise' //引入Promise
// axios 配置
axios.defaults.timeout = 5000; //设置超时时间
axios.defaults.baseURL = 'http://localhost:4000/api/v1/'; //这是调用数据接口
// http request 拦截器(所有发送的请求都要从这儿过一次),通过这个,我们就可以把token传到后台,我这里是使用sessionStorage来存储token等权限信息和用户信息,若要使用cookie可以自己封装一个函数并import便可使用
axios.interceptors.request.use(
config => {
const token = sessionStorage.getItem("token"); //获取存储在本地的token
config.data = JSON.stringify(config.data);
config.headers = {
'Content-Type':'application/json' //设置跨域头部,虽然很多浏览器默认都是使用json传数据,但咱要考虑IE浏览器。
};
if (token) {
config.headers.Authorization = "Token " + token; //携带权限参数
}
return config;
},
err => {
return Promise.reject(err);
}
);
// http response 拦截器(所有接收到的请求都要从这儿过一次)
axios.interceptors.response.use(
response => {
//response.status===401是我和后台约定的权限丢失或者权限不够返回的状态码,这个可以自己和后台约定,约定返回某个自定义字段也是可以的
if(response.status == 401) {
router.push({ //push后面是一个参数对象,可以携带很多参数,具体可以去vue-router上查看,例如query字段表示携带的参数
path: '/login'
})
}
return response;
},
error => {
return Promise.reject(error.response.data)
});
export default axios;
/**
* fetch 请求方法
* @param url
* @param params
* @returns {Promise}
*/
export function fetch(url, params = {}) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: params
})
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
/**
* post 请求方法
* @param url
* @param data
* @returns {Promise}
*/
export function post(url, data = {}) {
return new Promise((resolve, reject) => {
axios.post(url, data)
.then(response => {
resolve(response.data);
}, err => {
reject(err);
})
})
}
/**
* patch 方法封装
* @param url
* @param data
* @returns {Promise}
*/
export function patch(url, data = {}) {
return new Promise((resolve, reject) => {
axios.patch(url, data)
.then(response => {
resolve(response.data);
}, err => {
reject(err);
})
})
}
/**
* put 方法封装
* @param url
* @param data
* @returns {Promise}
*/
export function put(url, data = {}) {
return new Promise((resolve, reject) => {
axios.put(url, data)
.then(response => {
resolve(response.data);
}, err => {
reject(err);
})
})
}
03
(动态版),axios
的拦截器不是必要的,不是每个项目都需要,而且headers
里面的Content-Type
和Authorization
不止一种,这时就需要使用另一种方法。
util/http.js
import axios from 'axios' //引用axios
import {Promise} from 'es6-promise' //引入Promise
// axios 配置和拦截器都不用了,这里我使用了一个动态配置数据请求地址,在App.vue中,代码在下面,这个也不是必须的。
//^_^下面都设置一个默认的头部,使用的时候可以传入数据覆盖^_^,例如使用fetch(GET)方法时,没有请求数据,但是请求头有变化,则应写成 fetch("地址", {}, {"这里写头部的内容"}) 记住没数据用一个空对象占位置
/**
* fetch 请求方法
* @param url
* @param params
* @returns {Promise}
*/
export function fetch(url, params = {}, headers = {
'Content-Type': 'application/json', //设置跨域头部
"Authorization": 'JWT ' + sessionStorage.getItem("authToken")
}) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: params,
headers: headers
})
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err.response)
})
})
}
/**
* post 请求方法
* @param url
* @param data
* @returns {Promise}
*/
export function post(url, data = {}, config = {
"headers": {
'Content-Type': 'application/json', //设置跨域头部
"Authorization": 'JWT ' + sessionStorage.getItem("authToken")
}
}) {
return new Promise((resolve, reject) => {
axios.post(url, data, config)
.then(response => {
resolve(response.data);
}, err => {
reject(err.response);
})
})
}
/**
* patch 方法封装
* @param url
* @param data
* @returns {Promise}
*/
export function patch(url, data = {}, config = {
"headers": {
'Content-Type': 'application/json', //设置跨域头部
"Authorization": 'JWT ' + sessionStorage.getItem("authToken")
}
}) {
return new Promise((resolve, reject) => {
axios.patch(url, data, config)
.then(response => {
resolve(response.data);
}, err => {
reject(err.response);
})
})
}
/**
* put 方法封装
* @param url
* @param data
* @returns {Promise}
*/
export function put(url, data = {}, config = {
"headers": {
'Content-Type': 'application/json', //设置跨域头部
"Authorization": 'JWT ' + sessionStorage.getItem("authToken")
}
}) {
return new Promise((resolve, reject) => {
axios.put(url, data, config)
.then(response => {
resolve(response.data);
}, err => {
reject(err.response);
})
})
}
App.vue(这是在src
目录下的程序入口文件)
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
import axios from 'axios';
let protocol = window.location.protocol; //协议
let host = window.location.host; //主机
let reg = /^localhost+/;
if(reg.test(host)) {
//若本地项目调试使用
axios.defaults.baseURL = 'http://10.0.xx.xxx:xxxx/api/';
} else {
//动态请求地址
axios.defaults.baseURL = protocol + "//" + host + "/api/";
}
axios.defaults.timeout = 30000;
export default {
name: 'app',
axios //这里记得导出,若请求地址永久固定一个,则就按照`普通版`配置一个baserURL就可以了
}
</script>
<style lang="scss"> //这里我使用的是scss
@import '~@/style/style'
</style>
04
总结
-
常见问题
- 在使用动态版时,为什么称为动态呢,是因为访问地址和请求地址是同一个地址可端口号,例如我通过
https://www.xxx.com
(默认端口80)访问项目,那么我的baseURL
会自动的变为https://www.xxx.com:80/api/
,这么做的原因是当某一天项目迁移或者http
改为https
时,不用你再去更改请求地址,程序自动就完成了 - 数据请求地址配置不正确?如果你配置了
baseURL
,那么你封装的函数在使用时仅需传入基于baseURL
的请求地址,例如传入login/
那么请求地址会自动变为https://www.xxx.com:80/api/login/
,若未配置,那么可以直接传入整个请求地址
- 在使用动态版时,为什么称为动态呢,是因为访问地址和请求地址是同一个地址可端口号,例如我通过
-
注意事项
- 在使用动态版时,由于没有使用拦截器,所以下面封装的函数在返回错误的时候需要写成
err.response.data
来获取返回的数据,但我写的是err.response
,因为这样可以拿到(status)状态码
等信息,若不需要判断返回的状态码,则改为err.response.data
便可
- 在使用动态版时,由于没有使用拦截器,所以下面封装的函数在返回错误的时候需要写成
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。