維護(hù)loading加載狀態(tài)的幾個(gè)方法小結(jié)
前言
在項(xiàng)目開(kāi)發(fā)中,當(dāng)頁(yè)面請(qǐng)求接口時(shí),組件局部或者頁(yè)面全局顯示loading
加載遮罩可謂是司空見(jiàn)慣了,下面來(lái)討論一下如何優(yōu)雅的使用loading
狀態(tài)。下文引用了比較常用的兩個(gè)組件Button
按鈕和Table
表格作為例子,談?wù)勅绾蝺?yōu)雅的維護(hù)loading
加載狀態(tài)。
Butoon組件原始加載用法
<template> <div> <div>數(shù)據(jù):{{ list }}</div> <el-button type="primary" @click="asyncFetch" :loading="loading">異步獲取</el-button> <el-button type="primary" @click="syncFetch" :loading="loading">同步獲取</el-button> </div> </template> <script setup> import { ref } from 'vue' import { FetchApi } from '@/api' const loading = ref(false) const list = ref([]) // 異步調(diào)用 const asyncFetch = () => { loading.value = true FetchApi().then(res => { console.log(res) list.value = res }).finally(() => { loading.value = false }) } // 同步調(diào)用 const syncFetch = async () => { loading.value = true try { const res = await FetchApi() console.log(res) list.value = res } catch (error) { console.log(error) } loading.value = false } </script>
由以上代碼可看出,在每次點(diǎn)擊按鈕提交時(shí),都需要在調(diào)用接口前開(kāi)啟加載狀態(tài),在接口調(diào)用結(jié)束時(shí),無(wú)論成功與否,都結(jié)束加載狀態(tài)。為了簡(jiǎn)化這一操作步驟,減少代碼冗余,我們可以封裝一個(gè)button
組件,把loading
狀態(tài)及相關(guān)邏輯提取這個(gè)組件當(dāng)中。
封裝Button組件
<template> <!-- 新版本vue中,透?jìng)骺墒÷詖-bind="$attrs" --> <el-button v-bind="$attrs" :loading="loading" :onClick="handleClick"> <slot></slot> </el-button> </template> <script setup> import { ref } from 'vue' const { onClick } = defineProps(['onClick']) const loading = ref(false) // 重寫(xiě)點(diǎn)擊方法 const handleClick = async () => { loading.value = true try { // 傳遞的onClick方法必須為同步的 onClick && await onClick() } catch (error) { console.error(error) } loading.value = false } </script>
以上對(duì)button
組件進(jìn)行二次封裝,把一些重復(fù)的業(yè)務(wù)邏輯放到該組件中,為了能夠知道異步方法什么時(shí)候執(zhí)行結(jié)束,將點(diǎn)擊方法
通過(guò)prop
參數(shù)的形式傳遞到子組件中,交給子組件在合適的時(shí)機(jī)執(zhí)行,學(xué)過(guò)react
的話應(yīng)該對(duì)此操作比較熟悉。
組件加載用法
Page.vue
<template> <div> <div>數(shù)據(jù):{{ list }}</div> <ViButton type="primary" :onClick="syncFetch">同步獲取</ViButton> </div> </template> <script setup> import { ref } from 'vue' import { FetchApi } from '@/api' import ViButton from '@/components/ViButton/ViButton.vue' const list = ref([]) // 同步調(diào)用 const syncFetch = async () => { const res = await FetchApi() list.value = res } </script>
需要注意的是,我們需要把FetchApi()
異步方法轉(zhuǎn)為同步,這是為了在Button
組件中能夠方便地知道FetchApi方法
的執(zhí)行結(jié)束時(shí)機(jī),否則在Button
組件中將不能正確的隱藏loading
狀態(tài)。
封裝表格組件
<template> <!-- 新版本vue中,透?jìng)骺墒÷詖-bind="$attrs" --> <el-table v-bind="$attrs" v-loading="loading"> <slot></slot> </el-table> </template> <script setup> import { ref, onMounted } from 'vue' const props = defineProps({ // 獲取數(shù)據(jù)方法 fetchData: { type: Function, default: () => {} }, // 默認(rèn)是onMounted立即執(zhí)行fetchData immediateFetch: { type: Boolean, default: true } }) const loading = ref(false) const getList = async () => { loading.value = true try { await props.fetchData() } catch (error) { console.log(error) } loading.value = false } onMounted(() => { props.immediateFetch && getList() }) // 暴露經(jīng)過(guò)loading處理的fetch方法,比如搜索時(shí)候需要在父組件手動(dòng)調(diào)用 defineExpose({ fetchData: getList }) </script>
組件加載用法
page.vue
<template> <div> <ViTable ref="ViTableRef" :data="list" :fetchData="syncFetch" :immediateFetch="false"> <el-table-column prop="name" label="姓名"></el-table-column> </ViTable> <el-button @click="onSearch">查詢</el-button> </div> </template> <script setup> import { ref } from 'vue' import { FetchApi } from '@/api' import ViTable from '@/components/ViTable/ViTable.vue' const list = ref([]) const ViTableRef = ref(null) // 同步調(diào)用 const syncFetch = async () => { console.log('syncFetch') const res = await FetchApi() list.value = res console.log(list.value) } // 搜索 const onSearch = () => { ViTableRef.value.fetchData() } </script>
以上需要注意的有兩點(diǎn):
- 數(shù)據(jù)是否需要在表格掛載完成立即獲?。?/li>
- 需要對(duì)外暴露經(jīng)過(guò)
loading
加工的fetch
方法,目的是滿足需要手動(dòng)調(diào)用獲取數(shù)據(jù)的需求,比如點(diǎn)擊搜索;
以上方式當(dāng)需要手動(dòng)調(diào)用時(shí)似乎還是有些麻煩,下面我們改成useHook
方式來(lái)試試~
封裝useLoading鉤子函數(shù)
useLoading.js
import { ref } from 'vue' // 多個(gè)組件共享統(tǒng)一狀態(tài) const loading = ref(false) export const useLoading = (prop = { fetchData: () => {} }) => { // 對(duì)外暴露loading給table組件或者button組件使用 // 內(nèi)部只負(fù)責(zé)處理業(yè)務(wù)邏輯,不負(fù)責(zé)調(diào)用,這樣更加靈活 return { loading, fetchData: async () => { loading.value = true try { await prop.fetchData() } catch (error) { console.log(error) } loading.value = false } } }
ViTablePlus.vue
<template> <!-- 新版本vue中,透?jìng)骺墒÷詖-bind="$attrs" --> <el-table v-bind="$attrs" v-loading="loading"> <slot></slot> </el-table> </template> <script setup> import { useLoading } from '@/hooks/useLoading' const { loading } = useLoading() </script>
用法
Page.vue
<template> <div> <ViTablePlus :data="list" :fetchData="syncFetch" :immediateFetch="false"> <el-table-column prop="name" label="姓名"></el-table-column> </ViTablePlus> <el-button @click="onSearch">查詢</el-button> </div> </template> <script setup> import { ref, onMounted } from 'vue' import { FetchApi } from '@/api' import ViTablePlus from '@/components/ViTablePlus/ViTablePlus.vue' import { useLoading } from '@/hooks/useLoading' // 手動(dòng)執(zhí)行經(jīng)過(guò)loading處理的fetchData方法 const { fetchData } = useLoading({ fetchData: syncFetch }) const list = ref([]) // 需要使用function定義方法,進(jìn)行變量提升,因?yàn)閡seLoading在syncFetch方法定義前執(zhí)行 async function syncFetch() { const res = await FetchApi() list.value = res } // 搜索 const onSearch = () => { // 經(jīng)過(guò)loading處理的fetchData方法 fetchData() } onMounted(() => { // 經(jīng)過(guò)loading處理的fetchData方法 fetchData() }) </script>
總結(jié)
本文講了在二次封裝的Button
和Table
組件內(nèi)部維護(hù)loading
狀態(tài),為了能夠獲取到異步方法的調(diào)用完成時(shí)機(jī),我們把異步方法
轉(zhuǎn)為同步方法
后,通過(guò)prop
的方式傳遞到子組件,委托子組件在恰當(dāng)?shù)臅r(shí)機(jī)執(zhí)行。但把loading
狀態(tài)封裝到組件內(nèi)部還是不夠靈活,最后使用useLoading
鉤子函數(shù)維護(hù)一個(gè)全局狀態(tài),提供靈活的跨組件狀態(tài)共享。
以上就是維護(hù)loading加載狀態(tài)的幾個(gè)方法小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于維護(hù)loading加載狀態(tài)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript常見(jiàn)數(shù)組方法之如何轉(zhuǎn)置矩陣
這篇文章主要給大家介紹了關(guān)于JavaScript常見(jiàn)數(shù)組方法之如何轉(zhuǎn)置矩陣的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-03-03Javascript下拉刷新的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了Javascript下拉刷新的簡(jiǎn)單實(shí)現(xiàn)過(guò)程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02js+css實(shí)現(xiàn)的圓角邊框TAB選項(xiàng)卡滑動(dòng)門(mén)代碼分享(2款)
這篇文章主要為大家詳細(xì)介紹了兩種js+css實(shí)現(xiàn)的圓角邊框TAB選項(xiàng)卡滑動(dòng)門(mén)效果,很實(shí)用的代碼,推薦給大家,有需要的小伙伴可以參考下2015-08-08JavaScript面試Module?Federation實(shí)現(xiàn)原理詳解
這篇文章主要為大家介紹了JavaScript面試Module?Federation實(shí)現(xiàn)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Javascript數(shù)組的?splice?方法詳細(xì)介紹
這篇文章主要介紹了Javascript數(shù)組的splice方法詳細(xì)介紹,splice方法通過(guò)刪除或替換現(xiàn)有元素或者原地添加新的元素來(lái)修改數(shù)組,并以數(shù)組形式返回被修改的內(nèi)容。此方法會(huì)改變?cè)瓟?shù)組2022-09-09面向JavaScript入門(mén)初學(xué)者的二叉搜索樹(shù)算法教程
二叉搜索樹(shù)則是二叉樹(shù)的一種,但它只允許你在左側(cè)節(jié)點(diǎn)儲(chǔ)存比父節(jié)點(diǎn)小的值,右側(cè)只允許儲(chǔ)存比父節(jié)點(diǎn)大的值,這篇文章主要給大家介紹了關(guān)于JavaScript二叉搜索樹(shù)算法的相關(guān)資料,需要的朋友可以參考下2021-09-09總結(jié)JavaScript中布爾操作符||與&&的使用技巧
這篇文章主要介紹了總結(jié)JavaScript中布爾操作符||與&&的使用技巧,是JS入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-11-11