時間: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
函式。