现在vue项目基本上都是使用axios进行请求操作,但是axios有时候并不能完全满足业务的需求,因为官方axios只支持一些比较规则的请求参数和方式,比如body类型的post,params类型的get。
而实际业务中后台给的接口可不会那么如你所愿的规范,当后台同事肆意挥洒,尽情装逼,完全是即兴发挥,不考虑前端感受的时候,往往给出来的api接口是很变态的:
get方法的url后面拼接参数?
没办法,谁让前端是万能的呢,只能将就一下后台同事了。
实际项目中用到的最多的方式就是get和post,所以这里主要以封装get和post为例,patch、delete等方法封装与此类似。
分析:
get请求可以有的组合方式:
1、没有参数
2、有参数,参数以query的形式拼接在url上:api/customer?a=xxx&b=yyy
3、有参数,参数以path的形式拼接到url上:api/customer/xxx/yyy
4、有参数,参数以path的形式替换指定字段拼接到url上:api/customer/xxx/yyy
5、无参数,请求返回的数据为blob数据流形式
6、有参数,请求返回的数据为blob数据流形式,参数以path的形式拼接到url上,api/customer/xxx/yyy
7、有参数,请求返回的数据为blob数据流形式,参数以query的形式拼接到url上,api/customer?a=xxx&b=yyy
post请求可以有的组合方式:
1、没有参数
2、有参数,参数以json格式放在body里
3、有参数,参数以path的形式拼接到url上:api/customer/xxx/yyy
4、有参数,参数以query的形式拼接到url上:api/customer?a=xxx&b=yyy
5、无参数,上传formdata数据,部分参数以以json格式放在body里(选传)
6、有参数,上传formdata数据,部分参数以以json格式放在body里(选传),部分参数以path的形式拼接到url上,api/customer/xxx/yyy
7、有参数,上传formdata数据,部分参数以以json格式放在body里(选传),部分参数以query的形式拼接到url上,api/customer?a=xxx&b=yyy
8、无参数,接收blob数据流,部分参数以以json格式放在body里(选传)
9、无参数,接收blob数据流,部分参数以以json格式放在body里(选传),部分参数以path的形式拼接到url上,api/customer/xxx/yyy
10、无参数,接收blob数据流,部分参数以以json格式放在body里(选传),部分参数以query的形式拼接到url上,api/customer?a=xxx&b=yyy
大致就罗列了这么些可能的组合,太多了!
封装请求:
在文件目录下新建service>reset-api.js和service>api-urls.js
api-urls.js 存放所有api接口
const apis = {
// get
get: '/api/shop/customer/get', // get
getNormal: '/api/shop/customer/query', // query
getOrderPath: '/api/shop/customer/getOrderPath', // getOrderPath
getLocationPath: '/api/shop/customer/fileCode/page', // 指定字段替换
getBlob: '/api/shop/customer/getBlob', // getBlob
getPathBlob: '/api/shop/customer/getPathBlob', // getPathBlob
getQueryBlob: '/api/shop/customer/getQueryBlob', // getQueryBlob
// post
postBody: '/api/shop/customer/body', // body
postPath: '/api/shop/customer/body', // bodyPath
postQuery: '/api/shop/customer/body', // bodyQuery
postFormData: '/api/shop/customer/formData', // formData
postFormDataPath: '/api/shop/customer/formDataPath', // formDataAndPath
postFormDataQuery: '/api/shop/customer/formdataQuery', // formdataAndQuery
postBlob: '/api/shop/customer/postBlob', // postBlob
postBlobPath: '/api/shop/customer/postBlobPath', // postBlob
postBlobQuery: '/api/shop/customer/postBlobQuery', // postBlobQuery
};
export default apis
get封装
为防止ie下get方法读取缓存,在url后默认添加时间戳_t字段
1、没有参数的时候,可直接使用别名方法:
return axios.get(url, {
headers: {
token: token,
},
});
2、query形式参数,可使用params字段
return axios.get(url, {
params: data,
headers: {
token: token,
},
});
3、参数按path拼接到url上
if (Object.keys(data).length) {
for (let key in data) {
url += `/${data[key]}`;
}
}
url += `?_t=${Date.now()}`; // 加时间戳,防止ie取缓存
return axios.get(url, {
headers: {
token: token,
},
});
4、指定位置替换,path形式拼接到url上
url上必须包含需被替换的字段:api/customer/name/age
传参数时字段必须和要替换的一一对应:{name: 'abc',age:12}
被替换后:api/customer/abc/12
if (Object.keys(data).length) {
for (let key in data) {
let reg = new RegExp(key, 'g');
url = url.replace(reg, data[key]);
}
}
url += `?_t=${Date.now()}`; // 加时间戳,防止ie取缓存
return axios.get(url, {
headers: {
token: token,
},
});
5、请求blob数据流类型,没有参数
url += `?_t=${Date.now()}`; // 加时间戳,防止ie取缓存
return axios({
method: 'get',
url: url,
responseType: 'blob',
headers: {
token: token,
},
});
6、请求blob数据流类型,参数以path形式拼接
if (Object.keys(data).length) {
for (let key in data) {
url += `/${data[key]}`;
}
}
url += `?_t=${Date.now()}`; // 加时间戳,防止ie取缓存
return axios({
method: 'get',
url: url,
responseType: 'blob',
headers: {
token: token,
},
});
7、请求blob数据流类型,参数以query形式拼接
if (Object.keys(data).length) {
for (let key in data) {
url +=
url.indexOf('?') < 0
? `?${key}=${data[key]}`
: `&${key}=${data[key]}`;
}
}
url += `?_t=${Date.now()}`; // 加时间戳,防止ie取缓存
return axios({
method: 'get',
url: url,
responseType: 'blob',
headers: {
token: token,
},
});
post封装
1、无参数和json格式参数
return axios.post(url, data, {
headers: {
token: token,
},
});
3、有参数,部分json格式(可选),部分path拼接
if (Object.keys(config).length) {
for (let key in config) {
url += `/${config[key]}`;
}
}
return axios.post(url, data, {
headers: {
token: token,
},
});
4、有参数,部分json(可选),部分query拼接
if (Object.keys(config).length) {
for (let key in config) {
url +=
url.indexOf('?') < 0
? `?${key}=${config[key]}`
: `&${key}=${config[key]}`;
}
}
return axios.post(url, data, {
headers: {
token: token,
},
});
5、无参数,上传formdata(文件)
return axios.post(url, formData, {
headers: {
token: token,
'content-type': 'application/x-www-form-urlencoded',
},
});
6、有参数,上传formdata(文件),path拼接
if (Object.keys(config).length) {
for (let key in config) {
url += `/${config[key]}`;
}
}
return axios.post(url, formData, {
headers: {
token: token,
'content-type': 'application/x-www-form-urlencoded',
},
});
7、有参数,上传formdata(文件),query拼接
if (Object.keys(config).length) {
for (let key in config) {
url +=
url.indexOf('?') < 0
? `?${key}=${config[key]}`
: `&${key}=${config[key]}`;
}
}
return axios.post(url, formData, {
headers: {
token: token,
'content-type': 'application/x-www-form-urlencoded',
},
});
8、接收blob数据流,json格式(可选)
return axios({
method: 'post',
url: url,
data: data,
responseType: 'blob',
headers: {
token: token,
},
});
9、接收blob数据流,json格式(可选),有path拼接
if (Object.keys(config).length) {
for (let key in config) {
url += `/${config[key]}`;
}
}
return axios({
method: 'post',
url: url,
data: data,
responseType: 'blob',
headers: {
token: token,
},
});
10、接收blob数据流,json格式(可选),有query拼接
if (Object.keys(config).length) {
for (let key in config) {
url +=
url.indexOf('?') < 0
? `?${key}=${config[key]}`
: `&${key}=${config[key]}`;
}
}
return axios({
method: 'post',
url: url,
data: data,
responseType: 'blob',
headers: {
token: token,
},
});
最后统一整理一下reset-api.js
import Vue from 'vue';
import axios from 'axios';
import config from '@/config';
import apis from '@/service/api-urls';
import { sessionStore } from '@/utils';
const TIMEOUT = 10000; // 接口10秒超时
// console.log(config.envConfig)
const NODE_ENV = (process.env.NODE_ENV || 'development').trim();
const BASE_URL = NODE_ENV === 'development' ? config.envConfig.apiOrigin : '';
axios.defaults.timeout = TIMEOUT;
// 添加请求拦截
axios.interceptors.request.use(
function(config) {
// 请求之前处理
return config;
},
function(error) {
// 请求发生错误处理
return Promise.reject(error);
},
);
// 添加响应拦截
axios.interceptors.response.use(
function(response) {
return response;
},
function(error) {
return Promise.reject(error);
},
);
let createAxios = (baseURL, url) => {
function commonJoinPath(data, url) {
if (Object.keys(data).length) {
for (let key in data) {
url += `/${data[key]}`;
}
}
return url;
}
function commonJoinQuery(data, url) {
for (let key in data) {
url +=
url.indexOf('?') < 0
? `?${key}=${data[key]}`
: `&${key}=${data[key]}`;
}
return url;
}
return {
/*
* axios get 请求
* @param {Object} data - 需要的传参,选传,默认值为空对象
* @param {Object} config - 其他配置项,选传,默认值为空对象
* */
get(requestType, data = {}, config = {}) {
let token = sessionStore.get('userInfo')
? sessionStore.get('userInfo').token
: '12222';
// console.log(data, baseURL)
function commonGetPath(url, token) {
url += `?_t=${Date.now()}`; // 加时间戳,防止ie取缓存
return axios.get(url, {
headers: {
token: token,
},
});
}
function commonGetBlob(url, token) {
url += `?_t=${Date.now()}`; // 加时间戳,防止ie取缓存
return axios({
method: 'get',
url: url,
responseType: 'blob',
headers: {
token: token,
},
});
}
if (requestType === 'normal' || !requestType) {
// param参数类型
url += requestType ? '' : `?_t=${Date.now()}`; // 加时间戳,防止ie取缓存
data = requestType
? Object.assign({}, data, {
_t: Date.now(),
})
: data;
return axios.get(url, {
params: data,
headers: {
token: token,
},
});
}
if (requestType === 'orderPath') {
// 按顺序拼接到url上
url = commonJoinPath(data, url);
return commonGetPath(url, token);
}
if (requestType === 'locationPath') {
// 指定位置拼接到url上
if (Object.keys(data).length) {
for (let key in data) {
let reg = new RegExp(key, 'g');
url = url.replace(reg, data[key]);
}
}
// console.log(url)
return commonGetPath(url, token);
}
if (requestType === 'blob') {
// 返回值为blob数据流
return commonGetBlob(url, token);
}
if (requestType === 'pathBlob') {
// 返回值为blob数据流
url = commonJoinPath(data, url);
return commonGetBlob(url, token);
}
if (requestType === 'queryBlob') {
// 返回值为blob数据流
url = commonJoinQuery(data, url);
return commonGetBlob(url, token);
}
},
/*
* axios post 请求
* @param {Object} data - 需要的传参,选传,默认值为空对象
* @param {Object} config - 其他配置项,选传,默认值为空对象
* */
post(requestType, data = {}, config = {}) {
let token = sessionStore.get('userInfo')
? sessionStore.get('userInfo').token
: '2222';
console.log(requestType);
function commonPostBody(url, data, token) {
return axios.post(url, data, {
headers: {
token: token,
},
});
}
function commonPostFormData(url, formData, token) {
return axios.post(url, formData, {
headers: {
token: token,
'content-type': 'application/x-www-form-urlencoded',
},
});
}
function commonPostBlob(url, data, token) {
return axios({
method: 'post',
url: url,
data: data,
responseType: 'blob',
headers: {
token: token,
},
});
}
if (requestType === 'postNormal' || !requestType) {
return commonPostBody(url, data, token);
}
// 除了本身的body为json格式,部分参数以/形式拼接到url上
if (requestType === 'postPath') {
url = commonJoinPath(config, url);
return commonPostBody(url, data, token);
}
// 除了本身的body为json格式,部分参数以?a=xx&b=yy形式拼接到url上
if (requestType === 'postQuery') {
url = commonJoinQuery(config, url);
return commonPostBody(url, data, token);
}
// 只有formdata参数
if (requestType === 'formData') {
return commonPostFormData(url, data, token);
}
// 除了formdata参数,部分参数以/形式拼接到url上
if (requestType === 'postFormDataPath') {
url = commonJoinPath(config, url);
return commonPostFormData(url, data, token);
}
// 除了formdata参数,部分参数以?a=xx&b=yy形式拼接到url上
if (requestType === 'postFormDataQuery') {
url = commonJoinQuery(config, url);
return commonPostFormData(url, data, token);
}
// 返回值为blob
if (requestType === 'postBlob') {
console.log(data);
return commonPostBlob(url, data, token);
}
if (requestType === 'postBlobPath') {
url = commonJoinPath(config, url);
return commonPostBlob(url, data, token);
}
if (requestType === 'postBlobQuery') {
url = commonJoinQuery(config, url);
return commonPostBlob(url, data, token);
}
},
};
};
export const api = (key) => {
return createAxios(BASE_URL, apis[key]);
};
Vue.prototype.$api = api;
调用方式:
async get() {
let res = await this.$api('get').get();
},
async getQuery() {
let res = await this.$api('getNormal').get('normal', {
id: '123',
name: 'liang',
});
},
async getOrderPath() {
// 按顺序拼接
let res = await this.$api('getOrderPath').get('orderPath', {
fileCode: 'xxxxxxx',
page: 'x',
});
},
async getLocationPath() {
// 指定位置拼接
let res = await this.$api('getLocationPath').get('locationPath', {
fileCode: '122232323232',
page: '2',
});
},
async getBlob() {
// 没有参数
let resPrams = await this.$api('getBlob').get('blob');
},
async getPathBlob() {
// 有参数
let resPrams = await this.$api('getPathBlob').get('pathBlob', {
fileCode: 'xxxxxxx',
page: 'x',
});
},
async getQueryBlob() {
// 有参数
let resPrams = await this.$api('getQueryBlob').get('queryBlob', {
fileCode: 'xxxxxxx',
page: 'x',
});
},
// post
async post() {
let res = await this.$api('postBody').post();
},
async postBody() {
// body contentType:json
let res = await this.$api('postBody').post('postNormal', {
fileCode: 'xxxxxxx',
page: 'x',
});
},
async postPath() {
let res = await this.$api('postPath').post(
'postPath',
{
fileCode: 'xxxxxxx',
page: 'x',
},
{
path1: 222,
path2: 333,
},
);
},
async postQuery() {
let res = await this.$api('postQuery').post(
'postQuery',
{
fileCode: 'xxxxxxx',
page: 'x',
},
{
query1: 222,
query2: 333,
},
);
},
// 提交formData
postFromdata(options) {
let file = options.file;
let formData = new FormData();
formData.append('file', file);
this.$api('postFormData').post('formData', formData);
},
postFromdataPath(options) {
let file = options.file;
let formData = new FormData();
formData.append('file', file);
this.$api('postFormDataPath').post('postFormDataPath', formData, {
id: 123,
name: 'liang',
});
},
postFromdataQuery(options) {
let file = options.file;
let formData = new FormData();
formData.append('file', file);
this.$api('postFormDataQuery').post('postFormDataQuery', formData, {
id: 123,
name: 'liang',
});
},
// 返回值为blob类型
postBlob() {
this.$api('postBlob').post('postBlob',{ // data可为空对象
a:111,
b:222
});
},
postBlobPath() {
this.$api('postBlobPath').post( //data可为空对象
'postBlobPath',
{
fileCode: 'xxxxxxx',
page: 'x',
},
{
path1: 222,
path2: 333,
},
);
},
postBlobQuery() {
this.$api('postBlobQuery').post( // data可为空对象
'postBlobQuery',
{
fileCode: 'xxxxxxx',
page: 'x',
},
{
query1: 222,
query2: 333,
},
);
},