其實你不一定要在 onMounted 取 API

閱讀時間約 9 分鐘
鱈魚的魚缸搬家了!新家文章有重新修訂,歡迎來新家看看喔。(´▽`ʃ♡ƪ)
寫扣的鱈魚

寫扣的鱈魚

大家好,我是鱈魚。(。・∀・)ノ゙


最近看到大家討論取得 API 時機,有許多人都提到「一定要」或者「習慣」,在 onMounted 這個 hook 內呼叫 API 取得資料。


其實這也沒不好,但是也沒什麼好處就是了。(。・ω・。)


讓我們來思考一下下,有關於 Vue 取得 API 資料這檔事。(不會轉生,也沒有史萊姆

「一定要」在 onMounted

有人說「一定要」是因為不這麼做會壞掉,這個可以從 2 個部分來看。


首先是 onMounted 這個 hook 是甚麼?讓我們看看官網的定義:

Registers a callback to be called after the component has been mounted.

意思就是「註冊一個會在元件安裝完成後被呼叫的 callback」。


甚麼意思呢?也就是他和有沒有資料一點關係都沒有。換句話說 onMounted 沒辦法幫你保證有資料、template 不會壞,從此天下太平,再也不用加班,。(´。_。`)


所以就牽扯到了第二部分:為甚麼會壞掉?


馬上取會壞,onMounted 取就不會壞,這表示你的資料可能和 DOM 或元件發生耦合,這其實不是好現象,不但違反了資料驅動的概念還埋了隱形的翅膀…地雷。


具體原因可能如下:

  • API 參數耦合了某個 DOM 的資料,導致「沒有在 onMounted 取值」等於「對 undefined 動手動腳」,當然就壞掉惹。(〃` 3′〃)
  • API 參數或操作耦合了某個子元件,而 Vue 的 onMounted 會保證子元件都 onMounted 完後,自己的 onMounted 才會觸發,導致 onMounted 取才沒事。


所以總結來說,所謂的「壞掉」很有可能只是資料流沒考慮 undefined 的情境。


(可能啦,我巫力不足,只能通靈到這裡惹。 ╮(╯▽╰)╭)


如果有使用 TypeScript 就很少會出現這類問題了,因為 TypeScript 會先不開心、滿江紅給你看。ᕦ(ò_óˇ)ᕤ

「習慣」在 onMounted

習慣上可能會這樣寫:

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { getUser, User } from './api'

const user = ref<User>();

onMounted(async () => {
try {
user.value = await getUser();
} catch (error) {
console.error('QQ');
}
});
</script>

<template>
<h1>Classic</h1>
<div>
user: {{ user?.name }}
</div>
</template>


考慮讀取狀態則可能再加個 loading:

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { getUser, User } from './api'

const user = ref<User>();
const isLoading = ref(false);

onMounted(async () => {
try {
isLoading.value = true;
user.value = await getUser();
} catch (error) {
console.error('QQ');
} finally {
isLoading.value = false;
}
});
</script>

<template>
<h1>Classic</h1>
<div v-if="isLoading">
資料讀取中...(~﹃~)~zZ
</div>
<div v-else>
user: {{ user?.name }}
</div>
</template>


剛剛說了,其實不用在 onMounted 才取資料,早一點取也行,所以可以變成這樣:

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { getUser, User } from './api'

const user = ref<User>();
const isLoading = ref(true);

getUser().then((data) => {
user.value = data;
}).catch(() => {
console.error('QQ');
}).finally(() => {
isLoading.value = false;
});
</script>
...


路人:「這樣真的有比較好嗎?」

鱈魚:「當然沒有。(≧∇≦)ノ」

路人:(抄起球棒)

鱈魚:「冷靜冷靜,還沒說完啊。(っ °Д °;)っ」


來點 Composition

讓我們回想一下 Vue 3 的 Composition API 精神,一但要取得資料變多後,仔細觀察可以發現「資料、狀態(isLoading)、取資料的 function」會重複出現。


讓我們抽離、重組一下,新增一個檔案。

  • useAsyncData.ts
import { ref } from 'vue';

interface UseAsyncDataParam<Data> {
executor: () => Promise<Data>;
onError?: (error: unknown) => void;
}

export function useAsyncData<Data>(param: UseAsyncDataParam<Data>) {
const data = ref<Data>();
const isLoading = ref(true);

param.executor().then((result) => {
data.value = result;
}).catch((error) => {
param.onError?.(error);
}).finally(() => {
isLoading.value = false;
});

return {
data,
isLoading,
execute: param.executor,
}
}


(寫過 Nuxt 的朋友們一定會有熟悉的感覺。(. ❛ ᴗ ❛.))


現在讓我們用這個 useAsyncData 改寫一下剛剛的例子看看。

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { getUser, User } from './api'
import { useAsyncData } from './useAsyncData'

const {
data: user,
isLoading,
} = useAsyncData({
executor: () => getUser(),
onError() {
console.error('QQ');
},
});
</script>

<template>
<h1>Composable</h1>
<div v-if="isLoading">
資料讀取中...(~﹃~)~zZ
</div>
<div v-else>
user: {{ user?.name }}
</div>
</template>

就算有多個狀態要取得也變得更好組織程式碼了,是不是看起來乾淨許多呢?


恭喜我們重複造了 Nuxt 的 useAsyncData 與 VueUse 的 useAsyncState 的輪子了!

★,°:.ヽ(✿゚▽゚)ノ$:.°★


沒錯,雖然目前這個 useAsyncData 的功能很簡陋,有很多需要改進的部分,但是這就是上述兩個 API 的基礎精神。


不過 Nuxt 還包含了 SSR 行為,所以更加複雜,推薦大家可以看看 VueUse useAsyncState 的文件原始碼,一定可以獲益良多。


文章到此結束了,感謝您的閱讀,以上範例程式碼可以在此取得

有其他想法請不吝告訴我,鱈魚感謝您!(o゜▽゜)o☆

17會員
14內容數
各種鱈魚滾鍵盤的雜紀
留言0
查看全部
發表第一個留言支持創作者!
鱈魚的魚缸 的其他內容
pipe 代表函數式程式設計中的概念,利用多個功能結合在一起,資料依序通過每個功能進行處理。文章中介紹了 pipe 的優點、兩個等效的程式碼比較以及 remeda 套件的使用。詳細介紹了使用 pipe 的好處,並提供了多個相關的例子,展示了 pipe 可讀性的提升。
pipe 代表函數式程式設計中的概念,利用多個功能結合在一起,資料依序通過每個功能進行處理。文章中介紹了 pipe 的優點、兩個等效的程式碼比較以及 remeda 套件的使用。詳細介紹了使用 pipe 的好處,並提供了多個相關的例子,展示了 pipe 可讀性的提升。
你可能也想看
Google News 追蹤
Thumbnail
接下來第二部分我們持續討論美國總統大選如何佈局, 以及選前一週到年底的操作策略建議 分析兩位候選人政策利多/ 利空的板塊和股票
Thumbnail
🤔為什麼團長的能力是死亡筆記本? 🤔為什麼像是死亡筆記本呢? 🤨作者巧思-讓妮翁死亡合理的幾個伏筆
有一次半夜起來我一直哭,就覺得自己很孤單,結果被我先生發現了。 他說:你到底怎麼了,你幹嘛一個人在這邊哭? 我說:我不知道,我就覺得我自己好孤單喔! 他說:你孤單什麼?你還有什麼不滿的?你對我們這個生活你覺得有什麼不滿? 我說:沒有。 他說:那你為什麼要這樣子呢,你為什麼要把生活搞成自己在這邊自憐,
Thumbnail
我愛你, 當你依偎著我的時候 ; 我愛你, 即便你是跟我鬧脾氣的時候…… 我愛你, 當你想到我的時候; 我愛你, 當我沒想起你的時候 我愛你,因為你是我的孩子;但你永遠不屬於我。<我的愛>
銷售人員有時候已經將產品優點介紹得相當清楚,但就是沒辦法銷售成功,其實是因為沒有抓住顧客真正的需求。 前幾年有部日劇—「房仲女王」,講述故事主人翁三軒家萬智銷售房屋的故事。這部日劇,以較為誇張的方式拍攝,因此可以將它視為一部富有趣味性的戲劇來觀賞,但若仔細探究,會發現此戲劇也不乏一些銷售觀念。 在「
Thumbnail
我們在傳送訊息時,常以為別人都看得懂訊息裡面各種婉轉、幽微的意思。但其實,別人常常看不太懂、沒吸收到,許多誤會因此產生。
Thumbnail
0056 (元大高股息ETF) 最近填息了, 而且只花了十幾個交易日. 不過在填息之後, 然後呢? 有沒有影響你的持股數量? 填息雖然讓帳面資產增加, 但對大部分人是沒有影響的. 配息填息是我們不能控制的, 既然不能控制, 為何還要特別關注與在意呢? 例如有一檔股票配息2元......
Thumbnail
你不是擔心沒有人愛你, 你只是擔心沒有人用你要的方式愛你; 可是最後你還是會發現,你是對的, 沒有人能以你想要的方式愛你, 除了你自己…… 有心事的時候,總會想閉著雙眼, 靜靜的發呆,默默的想著。 日子裡,總是累多於美,不得不面對; 感情裡,總是疼多過醉,難免有心碎; 不願遇人說累,多累都
Thumbnail
每次問孩子:「爸爸、媽媽對你們多好,你們知道嗎?」他們總是絞盡腦汁之後才勉強說出:「爸媽賺錢養我們,很辛苦。」然後就不知道該說什麼了。為什麼孩子會如此不知感恩呢?恐怕是你站在成人的角度,想當然認為他們必定會感念親恩,因而產生的誤解。那麼,我們可以怎麼做呢?不如換個角度……
Thumbnail
摩摩喳喳到華山運動,結果遇到沒有創作靈感的美藍馬。到底,美藍馬想要創作的是什麼樣的作品呢!
Thumbnail
根據艾兒莎的經驗,99%的工作內容都透過與他人合作來完成,(剩下的1%是不用工作吧XD)而我們大多數的人都落在那99%。對於許多初入職場的年輕人來說,「團隊合作」四個字與日常工作緊密連結。
Thumbnail
很多不支持同婚的人都說,他們自己也有同性戀朋友,他們也關心這些朋友,祝福他們過上好生活。但是他們不同意修改民法。所以我們說他們歧視同性戀是不對的,他們沒有要傷害同性戀朋友。他們認為他們只是表達自己的......
Thumbnail
接下來第二部分我們持續討論美國總統大選如何佈局, 以及選前一週到年底的操作策略建議 分析兩位候選人政策利多/ 利空的板塊和股票
Thumbnail
🤔為什麼團長的能力是死亡筆記本? 🤔為什麼像是死亡筆記本呢? 🤨作者巧思-讓妮翁死亡合理的幾個伏筆
有一次半夜起來我一直哭,就覺得自己很孤單,結果被我先生發現了。 他說:你到底怎麼了,你幹嘛一個人在這邊哭? 我說:我不知道,我就覺得我自己好孤單喔! 他說:你孤單什麼?你還有什麼不滿的?你對我們這個生活你覺得有什麼不滿? 我說:沒有。 他說:那你為什麼要這樣子呢,你為什麼要把生活搞成自己在這邊自憐,
Thumbnail
我愛你, 當你依偎著我的時候 ; 我愛你, 即便你是跟我鬧脾氣的時候…… 我愛你, 當你想到我的時候; 我愛你, 當我沒想起你的時候 我愛你,因為你是我的孩子;但你永遠不屬於我。<我的愛>
銷售人員有時候已經將產品優點介紹得相當清楚,但就是沒辦法銷售成功,其實是因為沒有抓住顧客真正的需求。 前幾年有部日劇—「房仲女王」,講述故事主人翁三軒家萬智銷售房屋的故事。這部日劇,以較為誇張的方式拍攝,因此可以將它視為一部富有趣味性的戲劇來觀賞,但若仔細探究,會發現此戲劇也不乏一些銷售觀念。 在「
Thumbnail
我們在傳送訊息時,常以為別人都看得懂訊息裡面各種婉轉、幽微的意思。但其實,別人常常看不太懂、沒吸收到,許多誤會因此產生。
Thumbnail
0056 (元大高股息ETF) 最近填息了, 而且只花了十幾個交易日. 不過在填息之後, 然後呢? 有沒有影響你的持股數量? 填息雖然讓帳面資產增加, 但對大部分人是沒有影響的. 配息填息是我們不能控制的, 既然不能控制, 為何還要特別關注與在意呢? 例如有一檔股票配息2元......
Thumbnail
你不是擔心沒有人愛你, 你只是擔心沒有人用你要的方式愛你; 可是最後你還是會發現,你是對的, 沒有人能以你想要的方式愛你, 除了你自己…… 有心事的時候,總會想閉著雙眼, 靜靜的發呆,默默的想著。 日子裡,總是累多於美,不得不面對; 感情裡,總是疼多過醉,難免有心碎; 不願遇人說累,多累都
Thumbnail
每次問孩子:「爸爸、媽媽對你們多好,你們知道嗎?」他們總是絞盡腦汁之後才勉強說出:「爸媽賺錢養我們,很辛苦。」然後就不知道該說什麼了。為什麼孩子會如此不知感恩呢?恐怕是你站在成人的角度,想當然認為他們必定會感念親恩,因而產生的誤解。那麼,我們可以怎麼做呢?不如換個角度……
Thumbnail
摩摩喳喳到華山運動,結果遇到沒有創作靈感的美藍馬。到底,美藍馬想要創作的是什麼樣的作品呢!
Thumbnail
根據艾兒莎的經驗,99%的工作內容都透過與他人合作來完成,(剩下的1%是不用工作吧XD)而我們大多數的人都落在那99%。對於許多初入職場的年輕人來說,「團隊合作」四個字與日常工作緊密連結。
Thumbnail
很多不支持同婚的人都說,他們自己也有同性戀朋友,他們也關心這些朋友,祝福他們過上好生活。但是他們不同意修改民法。所以我們說他們歧視同性戀是不對的,他們沒有要傷害同性戀朋友。他們認為他們只是表達自己的......