在 Nuxt 3.9 封裝與管理 API 調用函式

建立專案

建立專案。

1
2
npx nuxi@latest init nuxt-api-management
cd nuxt-api-management

實作

修改 .env 檔。

1
NUXT_PUBLIC_SERVER_API_URL=https://jsonplaceholder.typicode.com

修改 nuxt.config.ts 檔。

1
2
3
4
5
6
7
8
9
10
11
import { defineNuxtConfig } from 'nuxt/config';

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
// ...
runtimeConfig: {
public: {
serverApiUrl: process.env.NUXT_PUBLIC_SERVER_API_URL,
},
},
});

建立 utils/to-raw-object.js 檔,用來消除物件的響應性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const toRawObject = (object) => {
if (Array.isArray(object)) {
return object.map((item) => toRawObject(item));
}
if (object !== null && typeof object === 'object') {
const rawObject = {};
Object.keys(object).forEach((key) => {
rawObject[key] = toRawObject(object[key]);
});
return rawObject;
}
return toRaw(object);
};

export default toRawObject;

建立 utils/create-client.js 檔,用來封裝 useFetch 函式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import toRawObject from './to-raw-object';

const fetch = (service, method) => (
(url, options) => (
useFetch(url, {
baseURL: useRuntimeConfig().public[`${service}ApiUrl`],
method,
...(options?.body instanceof FormData ? options : toRawObject(options)), // prevent interdependence
})
)
);

const createClient = (service) => {
const methods = ['GET', 'POST', 'PATCH', 'PUT', 'DELETE'];
const map = {};
methods.forEach((method) => {
map[method.toLowerCase()] = fetch(service, method);
});
return map;
};

export default createClient;

建立 services/server.js 檔。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* eslint-disable no-param-reassign */
const client = createClient('server');

const handleRequest = ({ options }) => {
const token = ''; // from store
options.headers = {
...options.headers,
Authorization: `Bearer ${token}`,
};
};

const handleResponse = ({ response }) => {
if (response.status === 401) {
navigateTo('/sign-out');
const { _data } = response;
console.log(_data.message);
}
};

const fetchPosts = () => client.get('/posts', {
onRequest: handleRequest,
onResponse: handleResponse,
});

export default {
fetchPosts
};

建立 services/index.js 檔。

1
2
3
4
5
6
7
import server from './server';

export {
server,
};

export default null;

使用

修改 app.vue 檔。

1
2
3
4
5
6
7
8
9
10
11
12
13
<script setup>
import { server } from '~/services';

const { data, error } = await server.fetchPosts();

console.log(data.value);
</script>

<template>
<div>
<NuxtWelcome />
</div>
</template>

啟動服務。

1
npm run dev

程式碼