混入的方法:
第一种形式:
创建axios:
传入接口地址,和接口需要的数据对象
那么问题来了,全局封装的有axios方法,为什么还要自己创建一个axios实例?
因为我们需要对要下载的文件名字,后端带的文件名做解码(动态文件名)
解码就解码呗,跟自己又创建实例有啥关系?
问题就出在:
我们全局响应拦截器当时为了取data数据方便,直接返回的是data,而我们要解码后端返回的文件名是在与config.data平级的headers中的,也就是config.headers。
我们在响应拦截器做一个判断:
所以,我们解决这个问题就可以用全局统一封装的axios进行导出操作:
第一步:我们封装的接口请求get方法 -> options对象的目的自己传递的选项合并到全局axios配置中:
第二步:导出接口根据上面统一封装的sendGet方法,传入参数,第一个为导出时携带的参数,第二个为导出时的类型(这也是原来自己创建axios实例与用全局封装的axios唯一的区别,因为token,headers这些字段都在全局axios统一置入了)
第三步:在组件中调用导出方法(这个方法是通过mixins混入的),并把参数传入和类型传入
第四步:混入的导出方法:得到导出方法传入的接口,因为axios返回的都是一个promise对象,所以直接去.then即可
exportFn(interfaceRequest) {
interfaceRequest
.then(res => {
var blob = res.data;
// FileReader主要用于将文件内容读入内存
var reader = new FileReader();
reader.readAsDataURL(blob);
// onload当读取操作成功完成时调用
reader.onload = e => {
var a = document.createElement("a");
// 获取文件名fileName
var fileName = res.headers["content-disposition"].split("=");
fileName = fileName[fileName.length - 1];
fileName = fileName.replace(/utf-8‘‘/g, "");
a.download = decodeURI(fileName);
a.href = e.target.result.toString();
this.$message.success(this.downFileTxt);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
})
.catch(error => {
if (error.response.data.type === "application/json") {
let reader = new FileReader();
reader.readAsText(error.response.data);
reader.onload = e => {
const { message } = JSON.parse(reader.result.toString());
this.$message.error(message);
};
}
});
}
最后:两个注意点
1.想用后端返回的导出文件名,需要让后端把headers给你返回出来
2.要想使用全局的axios封装的方法:
(1)需要在全局响应拦截器中做一个判断,不要直接返回config.data,这样就会拿不到文件名存储在的config.headers
(2) 把导出文件的类型以对象的形式合并到全局封装的sendGet方法中。