其實你不一定要在 onMounted 取 API

更新於 2024/08/26閱讀時間約 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☆

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