时间:2018年11月06日
这两天有这样的一个需求:在下载按钮上加一个下载中的loading动画。现在的情况是用户点击下载按钮时没有一点反馈,以为没点上,会点击好几次,之后一下就下载好几次。
这种问题是人之常情,所以解决它无可厚非,可是解决的时候遇到了一些比较麻烦的问题。
下载函数在点击执行按钮执行函数调用的别的文件的方法,就像下面这样:
// a文件
// 点击按钮执行的函数
const main = () => {
downloadFile()
}
// b文件
// 具体下载函数
const downloadFile = () => {
// 下载部分代码
}
复制代码
如果仅仅是这样还好,我可以在main
函数中加上修改是否展示加载动画的变量,比方说下面这样:
// a文件
// 点击按钮执行的函数
const main = () => {
loading = true;
downloadFile();
loading = false;
}
复制代码
可是这个downloadFile
函数是个异步函数,所以如果想上面这样写的话loading
变量只会瞬间变一下,不会在downloadFile
函数执行完成之后再变成false
。
一开始我是打算用promise
来把main
函数包裹起来,在then
里面把loading
改成false
。事实证明这种方法确实可行,只是需要把reslove
传递过去,比方说这样:
// a文件
// 点击按钮执行的方法
return new Promise((reslove) => {
const main = () => {
loading = true;
downloadFile(reslove);
loading = false;
}
})
// b文件
const downloadFile = (reslove) => {
// 下载部分代码
reslove();
}
复制代码
后来思考之后发现这样的做法其实有点多余,完全可以不用Promise
的。我们需要新建一个修改loading
值的函数。
setLoadingStatus = (err, status) => {
if (err) {
message.error(err.message || err);
return this.exportTableLoading = false;
}
this.exportTableLoading = status;
}
复制代码
调用方法也比较简单:
// 有错
setLoadingStatus(err, false);
// 没错
setLoadingStatus(null, true);
复制代码
之后我们把这个方法作为参数传递给downloadFile
函数,在downloadFile
函数中调用方法即可。
// b文件
const downloadFile = (setLoadingStatus) => {
// 下载部分代码
if (err) {
setLoadingStatus(err, false);
}
setLoadingStatus(null, true);
}
复制代码
这里我们不用担心说setLoadingStatus
函数被调用两次,因为如果有错,在执行setLoadingStatus
函数错误情况时,就会直接return
错误内容,就算下面有接收到setLoadingStatus
函数的正确情况也不会执行。
所以整体下来就是这样的:
// a文件
// 定义修改loading的函数
setLoadingStatus = (err, status) => {
if (err) {
message.error(err.message || err);
return this.exportTableLoading = false;
}
this.exportTableLoading = status;
}
// 点击按钮执行的函数
const main = () => {
loading = true;
downloadFile(setLoadingStatus);
}
// b文件
const downloadFile = (setLoadingStatus) => {
// 下载部分代码
if (err) {
setLoadingStatus(err, false);
}
setLoadingStatus(null, true);
}
复制代码
不同文件之间也可以互相调用函数,不用考虑传递过去之后就无法修改loading
值的问题,因为其本身调用的还是a
文件中的setLoadingStatus
函数。