使用Vue时我们常使用axios搭配食用,网上很多教程推荐的方法是直接把axios挂在Vue实例下使用,类似这样
Vue.axios = _axios;
window.axios = _axios;
Object.defineProperties(Vue.prototype, {
axios: {
get() {
return _axios;
}
},
$axios: {
get() {
return _axios;
}
},
});
然后在各个component中进行如下的使用
export default {
data() {
return {
notification: [],
users: []
}
},
methods: {
getUser() {
this.axios.get(....)
.then(...)
.catch(...);
}
}
}
但是这样使用会有一个弊端,就是整个methods中充斥着一大堆的ajax请求代码
往往后台在返回数据时还会封装一层data上去
{"success":true,"msg":"SUCCESS","data":{...}}
那么methods中还需要每次都判断请求成功与否、提示信息的展示,以及将返回值的data提取出来
一段伟大的意大利面组件诞生了!
请求代码和组件的视图业务逻辑重度耦合的情况,非常不利于请求代码的复用(听说Vue 3会支持函数式的组合方法提高复用)
为了将ajax请求和组件本身的逻辑分离,可以将api相关接口抽取成独立的插件
import Vue from "vue";
const prefix = 'api';
const preHandleResponse = response => {
if (response && response.data) {
if (response.data.success) {
return Promise.resolve(response.data);
} else {
return Promise.reject(response.data.msg);
}
}
return Promise.reject('请求异常,请联系管理员');
};
const preHandleUri = uri => `/${prefix}/${uri}`;
const sendGet = (uri, params, option) => {
return Vue.axios.get(preHandleUri(uri), {
params: params,
...option
}).then(response => preHandleResponse(response))
};
const sendPost = (uri, data, option) => {
return Vue.axios.post(preHandleUri(uri), data, option)
.then(response => preHandleResponse(response))
};
const sendPut = (uri, data, option) => {
return Vue.axios.put(preHandleUri(uri), data, option)
.then(response => preHandleResponse(response))
};
const sendPatch = (uri, data, option) => {
return Vue.axios.patch(preHandleUri(uri), data, option)
.then(response => preHandleResponse(response))
};
const sendDelete = (uri, data, option) => {
return Vue.axios.delete(preHandleUri(uri), data, option)
.then(response => preHandleResponse(response))
};
const api = {
memo: {
list(params) {
return sendGet('memo', params);
},
save(data) {
return sendPost('memo', data);
},
update(data) {
return sendPut(`memo/${data.id}`, data);
},
del(id) {
return sendDelete(`memo/${id}`);
}
},
}
const APIPlugin = {
install(Vue, options) {
Object.defineProperties(Vue.prototype, {
$api: {
get() {
return api;
}
},
});
}
};
Vue.use(APIPlugin);
export default api;
这样就可以很方便的在component中对请求进行使用,同时避免代码意大利面化
this.$api.memo
.list(Object.assign({}, {
pageNum: this.grid.pageNum,
pageSize: this.grid.pageSize
}, this.queryForm))
.then(result => {
this.grid.data = result.data.rows;
this.grid.total = result.data.total;
this.grid.loading = false;
})
可以看见,由于在api.js中我们已经将data提取出来,也对success字段作了判断,组件中的请求逻辑已经简化了许多
同时,还可以非常方便的定义prefix,即api的前缀路径,搭配一些后台的api-gateway将非常方便!