打地基階段,本篇要將call API的系統設計好,這是經過幾次個人專案後,覺得用起來最適合的方式。產品相關的功能是直接拿dummyjson的API,所以這邊一併把CORS也設定一下。
說明一下我的資料系統設計,call API時的系統流程會長這樣:
store call useAPI -> useAPI send request
用oFetch
來call API,官網有指出oFetch是全域的功能了,所以就不安裝其他工具了(aixos):
Nuxt uses ofetch to expose globally the $fetch helper for making HTTP requests.
整個專案都會透過useApi
去拿後端資料,
在useApi
這隻composable裡有兩個響應式資料:
這是最後的樣子:
import { FetchError } from "ofetch";
export default function useAPI() {
const fetchData: Ref<any> = ref();
const isLoading: Ref<boolean> = ref(false);
const callAPI = async (url: string) => {
isLoading.value = true;
try {
const response = await $fetch(url, { responseType: 'json' });
fetchData.value = response;
} catch (error) {
const FetchError = error as FetchError;
if (FetchError.response && FetchError.response.status === 404) {
throw showError({ statusCode: 404, statusMessage: 'API Not Found' })
} else {
throw showError({ statusCode: FetchError.response?.status, statusMessage: FetchError.message })
}
} finally {
isLoading.value = false;
}
}
return {
fetchData,
isLoading,
callAPI
};
}
useStore.ts
就定位// ./stores/useStore.ts
import { defineStore } from 'pinia';
import useAPI from '~/composables/useApi';
const storeName = 'test';
export const useTest = defineStore(storeName, () => {
const {
callAPI,
fetchData,
isLoading
} = useAPI();
const testCallApi = async () => {
return callAPI(`https://dummyjson.com/products`);
}
return {
testCallApi,
isLoading,
fetchData
}
});
pages/index.vue
使用store:<script setup lang="ts">
// stores
const testStore = useTest();
const {
testCallApi
} = testStore;
const {
fetchData
} = storeToRefs(testStore);
onMounted(async () => {
await testCallApi();
})
</script>
<template>
<div>
Page: index
{{ fetchData }}
</div>
</template>
<style scoped>
</style>
其實dummyjson的CORS是access-control-allow-origin: *
不過還是寫一下吧~一樣,拿./stores/useStore.ts
來做測試:
import { defineStore } from 'pinia';
import useAPI from '~/composables/useApi';
const storeName = 'test';
export const useTest = defineStore(storeName, () => {
...
const testCallApi = async () => {
return callAPI(`/api/products`);
}
return {
testCallApi,
...
}
});
接著在./pages/index.vue
呼叫:
<script setup lang="ts">
// stores
const testStore = useTest();
const {
testCallApi
} = testStore;
const {
fetchData
} = storeToRefs(testStore);
onMounted(async () => {
await testCallApi();
})
</script>
<template>
<div>
Page: index
{{ fetchData }}
</div>
</template>
<style scoped>
</style>
最後網頁成功顯示:
一開始在K call API的功能時,我是直接寫在一般assets/js/xx.js
的檔案裡,因為也覺得沒毛病;後來一個資深前輩跟我說,像我這樣的規劃,寫在composable裡會更好,所以就改成這樣的做法,覺得非常的合理。