获取数据
- $fetch
- useAsyncData
- useFetch
- useLazyFetch
- useLazyAsyncData
这些函数只能用在 setup or Lifecycle Hooks 中。
1.$fetch
server与client都会发送网络请求(有重复发送缺点,建议使用nuxt提供的hook)
// 1.使用 $fetch 来发起网络请求
// server and client
$fetch(BASE_URL + "/homeInfo", {
method: "GET",
}).then((res) => {
console.log(res);
});
2.useAsyncData
useAsyncData(url, () => $fetch(url))
在刷新页面时, 可以减少客户端发起的一次请求,服务端会发起请求
切换路由客户端会发起网络请求,服务端不会
会阻塞导航
<script setup>
const { data } = await useAsyncData('count', () => $fetch('/api/count'))
</script>
3.useFetch
useFetch接收URL并获取数据,而useAsyncData可能有更复杂的逻辑。
useFetch(url)几乎等同于useAsyncData(url, () => $fetch(url))
<script setup>
const { data: count } = await useFetch('/api/count')
</script>
文档
function useFetch(
url: string | Request | Ref<string | Request> | () => string | Request,
options?: UseFetchOptions<DataT>
): Promise<AsyncData<DataT>>
type UseFetchOptions = {
key?: string
method?: string
query?: SearchParams
params?: SearchParams
body?: RequestInit['body'] | Record<string, any>
headers?: { key: string, value: string }[]
baseURL?: string
server?: boolean
lazy?: boolean
immediate?: boolean
default?: () => DataT
transform?: (input: DataT) => DataT
pick?: string[]
watch?: WatchSource[]
}
type AsyncData<DataT> = {
data: Ref<DataT>
pending: Ref<boolean>
refresh: (opts?: { dedupe?: boolean }) => Promise<void>
execute: () => Promise<void>
error: Ref<Error | boolean>
}
refresh刷新,与响应式参数改变再次请求
<script setup lang="ts">
const count = ref(1);
// 1.点击刷新时, 是在server端发起网络请求, 客户端不会发起网络请求,水合之后客户端是可以当前数据
const { data, refresh, pending } = await useFetch<IResultData>(
BASE_URL + "/goods",
{
method: "POST",
body: {
count,
},
}
);
function refreshPage() {
count.value++; // 会自动从新发起网络请求
// refresh(); // client 刷新请求
}
</script>
使用拦截器
const { data, pending, error, refresh } = await useFetch('/api/auth/login', {
onRequest({ request, options }) {
// Set the request headers
options.headers = options.headers || {}
options.headers.authorization = '...'
},
onRequestError({ request, options, error }) {
// Handle the request errors
},
onResponse({ request, response, options }) {
// Process the response data
return response._data
},
onResponseError({ request, response, options }) {
// Handle the response errors
}
})
4.useLazyFetch
useLazyFetch 为useFetch提供了一个包装器,通过将lazy选项设置为true,在处理程序解析之前触发导航。不会阻塞导航
使用watch确保一定可以拿到这个data的数据
<template>
<div v-if="pending">
Loading ...
</div>
<div v-else>
<div v-for="post in posts">
<!-- do something -->
</div>
</div>
</template>
<script setup>
/* Navigation will occur before fetching is complete.
Handle pending and error states directly within your component's template
*/
const { pending, data: posts } = useLazyFetch('/api/posts')
watch(posts, (newPosts) => {
// Because posts starts out null, you won't have access
// to its contents immediately, but you can watch it.
})
</script>
5.useLazyAsyncData
useLazyAsyncData为useAsyncData提供了一个包装器,通过将lazy选项设置为true,在处理程序解析之前触发导航。
官方文档
useFetch 函数对比 axios
获取数据Nuxt推荐使用 useFetch 函数,为什么不是 axios ?
- useFetch 底层调用的是$fetch函数,该函数是基于unjs/ohmyfetch请求库,并与原生的Fetch API有者相同API
- unjs/ohmyfetch 是一个跨端请求库: A better fetch API. Works on node, browser and workers
- 如果运行在服务器上,它可以智能的处理对 API接口的直接调用。
- 如果运行在客户端行,它可以对后台提供的 API接口 正常的调用(类似 axios),当然也支持第三方接口的调用
- 会自动解析响应和对数据进行字符串化
- useFetch 支持智能的类型提示和智能的推断 API 响应类型。
- 在setup中用useFetch获取数据,会减去客户端重复发起的请求
请求封装
import type { AsyncData, UseFetchOptions } from "nuxt/dist/app/composables";
const BASE_URL = "http://codercba.com:9060/juanpi/api/";
type Methods = "GET" | "POST";
export interface IResultData<T> {
code: number;
data: T;
}
class HYRequest {
request<T = any>(
url: string,
method: Methods,
data?: any,
options?: UseFetchOptions<T>
): Promise<AsyncData<T, Error>> {
return new Promise((resolve, reject) => {
const newOptions: UseFetchOptions<T> = {
baseURL: BASE_URL,
method: method,
...options,
};
if (method === "GET") {
newOptions.query = data; // query -> params
}
if (method === "POST") {
newOptions.body = data;
}
useFetch<T>(url, newOptions as any)
.then((res) => {
// res => { data:T, pending, refresh, error ... } => AsyncData
resolve(res as AsyncData<T, Error>);
})
.catch((error) => {
reject(error);
});
});
}
get<T = any>(url: string, params?: any, options?: UseFetchOptions<T>) {
return this.request(url, "GET", params, options);
}
post<T = any>(url: string, data?: any, options?: UseFetchOptions<T>) {
return this.request(url, "POST", data, options);
}
}
export default new HYRequest();
Server API
- Nuxt自动扫描~/server/api, ~/server/routes, 和 ~/server/middleware目录中的文件,以注册具有HMR支持的API和服务器处理程序。
- 每个文件都应该导出一个用defineEventHandler()定义的默认函数。
- 处理程序可以直接返回JSON数据,一个Promise或使用event.node.res.end()发送响应。
实例
创建一个新文件server/api/homeInfo.ts:
export default defineEventHandler((event) => {
let { req, res } = event.node;
console.log(req.method);
console.log(req.url);
return {
code: 200,
data: {
name: "liujun",
age: 18,
},
};
});
你现在可以使用await $fetch(‘/api/homeInfo’)通用地调用这个API。
官方文档server