1、问题描述
async downloadTemplate() {
try {
let res = await planModel.getTemplate();
let url = res.url;
let name = '里程碑计划.xlsx';
this.downloadFile(url, name);
} catch (error) {
console.error('下载文件时发生错误:', error);
}
},
downloadFile(url, filename) {
// 获取文件流
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function() {
if (this.status === 200) {
let blob = new Blob([this.response], {type: 'application/octet-stream'});
this.saveAs(blob, filename);
}
};
xhr.onerror = function() {
console.error('下载文件时网络错误');
};
xhr.send();
},
saveAs(blob, filename) {
if (window.navigator.msSaveOrOpenBlob) {
// IE 浏览器
navigator.msSaveBlob(blob, filename);
} else {
// 其他浏览器
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(link.href);
}
} ,---plan-batch-milepost.vue:98 Uncaught TypeError: this.saveAs is not a function
at xhr.onload (plan-batch-milepost.vue:98:16)
2、原因及解决措施
在您的代码中,this.saveAs
在 xhr.onload
回调函数中抛出 Uncaught TypeError: this.saveAs is not a function
错误,这是因为回调函数中的 this
上下文已经改变,不再指向 Vue 实例。要解决这个问题,您需要在回调函数外部保持对 Vue 实例的引用,然后在回调函数内部使用这个引用。
下面是修改后的代码,其中添加了一个 self
变量来保存 Vue 实例的引用:
javascript复制代码
export default { | |
methods: { | |
async downloadTemplate() { | |
try { | |
let res = await planModel.getTemplate(); | |
let url = res.url; | |
let name = '里程碑计划.xlsx'; | |
this.downloadFile(url, name); | |
} catch (error) { | |
console.error('下载文件时发生错误:', error); | |
} | |
}, | |
downloadFile(url, filename) { | |
let self = this; // 保存当前 Vue 实例的引用 | |
// 获取文件流 | |
let xhr = new XMLHttpRequest(); | |
xhr.open('GET', url, true); | |
xhr.responseType = 'blob'; | |
xhr.onload = function() { | |
if (this.status === 200) { | |
let blob = new Blob([this.response], {type: 'application/octet-stream'}); | |
self.saveAs(blob, filename); // 使用 Vue 实例的引用来调用 saveAs 方法 | |
} | |
}; | |
xhr.onerror = function() { | |
console.error('下载文件时网络错误'); | |
}; | |
xhr.send(); | |
}, | |
saveAs(blob, filename) { | |
if (window.navigator.msSaveOrOpenBlob) { | |
// IE 浏览器 | |
navigator.msSaveBlob(blob, filename); | |
} else { | |
// 其他浏览器 | |
let link = document.createElement('a'); | |
link.href = window.URL.createObjectURL(blob); | |
link.download = filename; | |
link.style.display = 'none'; | |
document.body.appendChild(link); | |
link.click(); | |
document.body.removeChild(link); | |
window.URL.revokeObjectURL(link.href); | |
} | |
} | |
} | |
} |
在这个修改后的代码中,self
变量在 downloadFile
方法的开始处被赋值为 this
,这样 self
就引用了 Vue 实例。然后,在 xhr.onload
回调函数中,我们使用 self.saveAs(blob, filename);
来调用 saveAs
方法,而不是 this.saveAs(blob, filename);
。这样,不论回调函数如何改变 this
的上下文,self
始终指向 Vue 实例,因此能够正确地调用 saveAs
方法。