背景
前兩天在開發一個管理後臺專案時, 遇到了一個問題,後端介面返回特別慢,由於該介面呼叫的是第三方API,無法通過後端去處理。此時想到用loading動畫,但隨之而來也產生了不少問題, 在此記錄一下以方便大家能夠遇到此類問題可以借鑑。
處理方案
在表格內新增loading
<el-table
v-loading="loading"
:data="tableData"
border
tooltip-effect="dark"
:row-class-name="tableRowClassName"
style="margin-top: 20px"
>
...
</el-table>
此種方式很簡單,在請求開始前設定loading為true,結束後設置為false。element官網也有詳細的概述,在此不過多描述。
在全域性內容容器內新增動畫
第一種方式確實簡單,但開發後UI效果並不是特別理想,所以考慮在內容容器內新增loading。此時使用了以服務的方式載入loading。
但此時也出現了一些問題, 首先在請求開始後,立即切換到其它頁面,此時還在顯示全域性loading。
而且再次切回該頁面又會再次發起請求,loading顯示位置也不正常。
切換路由是要取消請求和loading的,我們需要在元件路由生命週期內進行監聽。在離開此路由時,取消此次請求。
以下為具體程式碼:
離開路由生命週期
beforeRouteLeave(to, from, next) {
// 導航離開該元件的對應路由時呼叫
// 可以訪問元件例項 `this`
this.source.cancel("離開此頁面取消請求");
next();
},
...
請求事件
getTable() {
const CancelToken = axios.CancelToken;
this.source = CancelToken.source();
const options = {
target: ".el-main",
text: "拼命載入中...",
spinner: "el-icon-loading",
lock: true,
background: "rgba(255,255,255,0.4)",
};
const loadingInstance = this.$loading(options);
this.axios
.post(
"***",
qs.stringify({
name: this.q,
page: this.listQuery.page,
}),
{
cancelToken: this.source.token,
}
)
.then((res) => {
this.tableData = res.data.data;
this.$nextTick(() => {
// 以服務的方式呼叫的 Loading 需要非同步關閉
loadingInstance.close();
});
})
.catch((thrown) => {
// 如果請求被取消則進入該方法判斷
if (axios.isCancel(thrown)) {
console.log("Request canceled", thrown.message);
this.$nextTick(() => {
// 以服務的方式呼叫的 Loading 需要非同步關閉
loadingInstance.close();
});
} else {
// handle error
}
});
},
在離開頁面的同時取消請求,關閉loading動畫。
感悟
此次為了追求使用者體驗感更好,為此也走了不少的彎路,但我覺得還是很有意義的。同時也學到了不少新東西,如怎麼取消一個請求等。還是很有收穫的。