背景:基于vue-cli,对axios进行二次封装
流程:
(1)建立api层,对api进行独立管理;
(2)管理axios实例,对请求进行前后拦截;
(3)接口api化,方法请求自动绑定,防止重复提交。
代码:
1、在src文件夹中创建api文件夹,以独立管理api。
创建index.js统一管理所有api,创建需要用到的api:login.js、shop.js
login.js:(登录api)
export default {
'loginIn': '/api/loginIn',
'loginOut': '/api/loginOut'
}
shop.js:(商城api)
export default {
'shopList': '/api/shopList'
}
index.js:(管理api)
import login from './login.js'
import shop from './shop.js'
import myserver from '../request/getrequest.js';
myserver.parseRoutes('login', login);
myserver.parseRoutes('shop', shop);
export default myserver
在./src/main.js中引入./src/api/index.js:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import qa from './api/index.js'
Vue.prototype.qa = qa;
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
2.在src文件夹中创建request文件夹处理请求
request文件夹中创建server.js:管理api实例,拦截请求
request文件夹中创建getrequest.js:接口化api(login.loginIn()时就能充当axios请求),请求自动绑定(将返回的数据自动绑定到变量上), 防止重复提交请求
server.js:(管理api实例,拦截请求)
import axios from 'axios'
// 创建axios实例
const server = axios.create({
baseURL: 'http://192.168.0.22:9002',
timeout: 5000
})
function getLocalToken() {
let token = sessionStorage.getItem('token') || '';
return token;
}
// 请求前拦截
server.interceptors.request.use(
config => {
if(getLocalToken()) {
config.headers['token'] = getLocalToken();
config.headers['Content-Type'] = 'application/json;charset=utf-8';
}
return config;
},
error => {
console.log(error);
Promise.reject(error);
}
)
// 响应拦截
server.interceptors.response.use(
response => {
let res = response.data;
if(res.code == '401') {
console.log(401)
} else if (res.code == '402') {
console.log(402)
}
return Promise.resolve(res);
},
error => {
console.log(error);
Promise.reject(error);
}
)
export default server
getrequest.js:接口化api(login.loginIn()时就能充当axios请求),请求自动绑定(将返回的数据自动绑定到变量上), 防止重复提交请求
import server from './server.js'
import qs from 'qs'
// 创建myserver类
function myserver() {
this.server = server;
this.nowhandle = null;
}
// 解析api,并将接口api化,使得用this.login.loginIn()就能执行axios请求
myserver.prototype.parseRoutes = function(moduleName,urlObj) {
this[moduleName] = {};
Object.keys(urlObj).forEach(item => {
console.log(this[moduleName]);
this[moduleName][item] = this.sendMsg.bind(this, moduleName, item, urlObj[item]);
this[moduleName][item].state = 'ready';
})
}
// 获取当前vue组件
myserver.prototype.v = function(vueobj) {
this.nowhandle = vueobj;
return this;
}
// config:用户自定义配置(data:提交的数据,type:请求类型, bindName:要绑定的变量, success:成功回调, fail:失败回调)
myserver.prototype.sendMsg = function(moduleName, itemName, url, config) {
console.log(config);
let data = config.data || '';
let type = config.type || 'get';
let bindName = config.bindName || '';
let self = this;
// 成功
function defaultFn(res) {
if(bindName != '') {
self.nowhandle[bindName] = res;
}
}
let success = config.success || defaultFn;
function callback(res) {
return success(res, defaultFn);
}
// 失败
function defaultFailFn() {
console.log(error)
}
let fail = config.fail || defaultFailFn;
function failCallback() {
return fail(error, defaultFailFn)
}
let state = {
get: () => {
let urlqs = url + '?' + qs.stringify(data);
server.get(urlqs).then(callback).catch(failCallback);
},
post: () => {
server.post(url,data).then(callback).catch(failCallback);
}
}
// 防止重复请求
if(this[moduleName][itemName].state == 'ready') {
this[moduleName][itemName].state = 'pending';
state[type]();
}
}
export default new myserver;
3.在./src/components/HelloWorld.vue组件中使用:
<template>
<div class="hello">
<h1>{{login}}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
login: ''
}
},
mounted() {
this.qa.v(this)
this.qa.login.loginIn({
type: 'get',
data: {
a:123
},
bindName: 'login',
success(res, defaultFn) {
console.log(res);
console.log(defaultFn);
},
fail(error, defaultFn) {
console.log(error);
console.log(defaultFn);
}
})
}
}
</script>