本篇文章同步更新於個人部落格,歡迎交流指教~謝謝您的閱讀
Nuxt3 提供了全域可使用的內建函式庫 $fetch
以及 composables useFetch
、useAsyncData
,不需要在另外安裝套件,三個方法依據時機搭配使用,可以確保整體兼容性與快取效能,且能避免重複請求的問題
Nuxt2 的
asyncData
以及fetch
方法,在 Nuxt3 調整為useAsyncData
與useFetch
Nuxt3 使用 ofetch 建立全域使用 $fetch
方法,適合用來處理 透過使用者互動觸發的 API 請求
注意:
$fetch
不適合直接定義在 setup function,會導致 API 請求兩次,伺服器端跟用戶端各一次,因為$fetch
不會將狀態從伺服器端傳輸到用戶端
如果要在 setup function 定義,官方建議使用useFetch
或是useAsyncData
+$fetch
使用方式:
$fetch(url, options)
參數:
POST
、PUT
、PATCH
、DELETE
預設 0)onRequest
、onRequestError
、onResponse
、onResponseError
,見下面說明範例: 將 $fetch
包裝在 submit()
方法內,填寫完表單後,按下送出發出 API 請求
<template>
<div>
<label for="name">name</label>
<input type="text" name="name" v-model="user.name">
<label for="phone">phone</label>
<input type="text" name="phone" v-model="user.phone">
<button type="button" @click="submit()">submit</button>
</div>
</template>
<script setup>
const user = reactive({
name: '',
phone: ''
});
const submit = async () => {
const response = await $fetch('/api/user', {
method: 'POST',
body: { ...user }
});
console.log('success', response);
};
</script>
const response = await $fetch('/api/user', {
onRequest({ request, options }) {
// 設定請求時的 headers
options.headers.authorization = '...'
},
onRequestError({ request, options, error }) {
// 捕捉請求時發生的錯誤
},
onResponse({ request, response, options }) {
// 處理請求回覆資料
return response._data;
},
onResponseError({ request, response, options }) {
// 捕捉請求回覆時發生的錯誤
}
})
非同步函式的封裝組合方法,不能直接發出 API 請求,要搭配 handler
非同步函式使用,在 setup function 直接觸發,於伺服器端發出請求取得資料,並將狀態傳輸到用戶端
使用方式(搭配 $fetch
handler):
useAsyncData(key, () => $fetch(url))
參數:
useAsyncData
會自動產生false
,因此會在函式執行完成,取得資料後才切換畫面lazy: true
特別適用true
handler
請求的結果handler
回傳結果如果為物件,可以選擇需要的 key 組成新物件true
回傳值:
範例:
<template>
<div>
{{ user }}
<button type="button" @click="lastUser()">prev</button>
<button type="button" @click="nextUser()">next</button>
</div>
</template>
<script setup>
const id = ref(1);
const url = computed(() => `/api/user/${id.value}`);
const { data: user, refresh } = useAsyncData('user', () => $fetch(url.value));
const nextUser = () => {
id.value++;
refresh();
};
const lastUser = () => {
id.value--;
refresh();
};
</script>
為 useAsyncData
跟 $fetch
包裝後的語法糖,等同於:useAsyncData(key, () => $fetch(url))
。
請求時會依據 url 跟 options 自動產生 key
,在 setup function 直接觸發,於伺服器端發出請求取得資料,並將狀態傳輸到用戶端。可以使用 $fetch
的攔截器 onRequest
、onRequestError
、onResponse
、onResponseError
。
使用方式:
useFetch(url, options)
參數: 繼承 $fetch
跟 useAsyncData
的選項
回傳值: 繼承 useAsyncData
的回傳值
範例:
<template>
<div>
{{ data }}
<button type="button" @click="refresh()">refresh</button>
</div>
</template>
<script setup>
const { data, pending, refresh, execute, error, status } = useFetch('/api/users');
</script>
當參數為響應式時(ref, reactive, computed),useFetch
會自動發出請求
範例: 當狀態改變,useFetch
會自動重新觸發,因此我們只需要專注在 id
的變化即可
<template>
<div>
{{ userInfo }}
<button type="button" @click="lastUser()">last</button>
<button type="button" @click="nextUser()">next</button>
</div>
</template>
<script setup>
const id = ref(1);
const url = computed(() => `/api/user/${id.value}`);
const { data: userInfo } = useFetch(url);
const lastUser = () => {
id.value--;
};
const nextUser = () => {
id.value++;
};
</script>
比較範例:使用 $fetch
取代 useFetch
前面提到使用 $fetch
請求需透過函式包裝,如以下範例 getData()
,以避免重複請求,除了需在生命週期先呼叫 getData()
,當 id
更新時也需要手動觸發 getData()
,相對的維護跟易讀性較低
<template>
<div class="m-4">
{{ userInfo }}
<button type="button" @click="lastUser()">last</button>
<button type="button" @click="nextUser()">next</button>
</div>
</template>
<script setup>
const id = ref(1);
const userInfo = ref({});
const getData = async () => {
const response = await $fetch(`/api/user/${id.value}`);
userInfo.value = response;
};
onMounted(() => {
getData();
});
const lastUser = () => {
id.value--;
getData();
};
const nextUser = () => {
id.value++;
getData();
};
</script>
等同於 useAsyncData
與 useFetch
options 設定 lazy: true
參考資源:
https://medium.com/comsystoreply/nuxt-3-usefetch-reactive-vue-at-its-best-14729f6f5be7
https://ithelp.ithome.com.tw/articles/10298741