什么是useFetch
Nuxt.js 是一个基于 Vue.js 的通用应用框架,用于构建服务器渲染的应用程序(也称为通用应用程序或同构应用程序)。它简化了使用 Vue.js 构建服务器渲染应用程序的过程,并提供了许多开箱即用的功能和最佳实践。
Nuxt.js 的目标是帮助开发者构建高性能、可扩展的应用程序。它提供了许多功能,如自动代码分割、异步数据加载、静态站点生成等,使开发过程更加简单和高效。同时,Nuxt.js 也支持许多插件和模块,可以轻松地集成第三方库或添加自定义功能。
useFetch 是一个自定义的 nuxt Hook api,用于在组件中进行数据获取。它封装了使用 fetch
或其他 HTTP 客户端库进行数据请求的逻辑,并提供了一种简单的方式来处理异步数据的加载、错误和状态管理。
useFetch VS axios
获取数据Nuxt推荐使用useFetch函数,为什么不是axios?
useFetch底层调用的是$fetch函数,该函数是基于unjs/ohmyfetch请求库,并与原生的Fetch API有者相同API
unjs/ohmyfetch是一个跨端请求库:A better fetch API..Works on node,browser and workers
H。
√ 如果运行在服务器上,它可以智能的处理对AP接口的直接调用。
√ 如果运行在客户端行,它可以对后台提供的APl接口正常的调用(类似xios),当然也支持第三方接口的调用
√ 会自动解析响应和对数据进行字符串化
√ useFetch支持智能的类型提示和智能的推断API响应类型.
√ 在setupi中用useFetch获取数据,刷新页面时会减去客户端重复发起的请求。
useFetch的封装
新建service/index.ts
import { UseFetchOptions } from "nuxt/app";
type Methods = "GET" | "POST" | "DELETE" | "PUT";
const BASE_URL = "http://127.0.0.1:8090";
export interface IResultData<T> {
code: number;
data: T;
msg: string;
}
class HttpRequest {
request<T = any>(
url: string,
method: Methods,
data: any,
options?: UseFetchOptions<T>,
) {
return new Promise((resolve, reject) => {
const newOptions: UseFetchOptions<T> = {
baseURL: BASE_URL,
method: method,
...options,
};
if (method === "GET" || method === "DELETE") {
newOptions.params = data;
}
if (method === "POST" || method === "PUT") {
newOptions.body = data;
}
useFetch(url, newOptions)
.then((res) => {
resolve(res);
})
.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);
}
Put<T = any>(url: string, data: any, options?: UseFetchOptions<T>) {
return this.request(url, "PUT", data, options);
}
Delete<T = any>(url: string, params: any, options?: UseFetchOptions<T>) {
return this.request(url, "DELETE", params, options);
}
}
const httpRequest = new HttpRequest();
export default httpRequest;
让我们逐步分析这个代码片段:
首先,我们看到了import { UseFetchOptions } from "nuxt/app";
,这是引入了nuxt/app
模块中的UseFetchOptions
类型。UseFetchOptions
类型是一个用于配置请求选项的接口或类型。
定义了一个类型别名Methods
,它被限制为字符串字面量类型,只能是"GET"
、"POST"
、"DELETE"
或"PUT"
中的一个。这个别名用于表示 HTTP 请求的方法。
定义了一个常量BASE_URL
,它表示基本的 URL 地址,这个地址将与具体的请求路径拼接在一起。在这个示例中,BASE_URL
被设置为http://127.0.0.1:8080
,你可以根据实际情况修改为你的 API 地址。
接下来是一个泛型接口IResultData<T>
,它表示请求的结果数据的格式。该接口有三个属性:code
表示请求的返回码,data
表示请求返回的数据,msg
表示请求返回的消息。
然后,我们定义了一个名为HttpRequest
的类。这个类封装了发送 HTTP 请求的方法。
request
方法是这个类的核心方法。它接受四个参数:url
表示请求的路径,method
表示请求的方法,data
表示请求的数据,options
表示请求的选项。
在request
方法内部,我们首先创建了一个新的选项对象newOptions
,它继承了UseFetchOptions
类型。这个对象包含了baseURL
和method
两个属性,baseURL
被设置为我们之前定义的BASE_URL
常量,method
被设置为传入的请求方法。
接下来,我们根据请求方法的不同,决定如何处理请求的数据。如果请求方法是GET
或DELETE
,我们将数据设置为newOptions
的params
属性;如果请求方法是POST
或PUT
,我们将数据设置为newOptions
的body
属性。
我们使用useFetch
函数来发送请求,该函数接受请求的路径和选项对象作为参数,并返回一个 Promise 对象。当请求成功时,我们将结果通过resolve
方法传递出去;当请求失败时,我们通过reject
方法将错误抛出。
紧接着,我们定义了一系列封装的常用方法:get
、post
、put
和delete
。这些方法分别对应于 GET、POST、PUT 和 DELETE 请求,并在内部调用了request
方法来发送请求。
最后我们导出这个类对象, 以便使用。
api统一管理
在项目根目录创建api文件夹统一管理api
// api/staff.ts
import httpRequest from "~/service";
/**
* @description 分页查询员工数据
* @return 员工信息
*/
const URL = "/staff";
const getStaffInfoByPage = (params: any) => {
return httpRequest.get(URL, params);
};
/**
* @description 修改员工数据
* @param {any} data
* @returns {any}
*/
const updateStaffInfo = (data: any) => {
return httpRequest.post(URL, data);
};
export { getStaffInfoByPage, updateStaffInfo };
httpRequest
模块被导入并使用,getStaffInfoByPage
函数用于进行分页查询员工数据。它接收一个参数params
,该参数用于传递查询条件或分页参数。在函数内部,它使用了一个名为httpRequest
的模块来发起HTTP GET请求,请求的URL为/staff
,并将params
作为查询参数传递给请求。该函数返回一个Promise,用于处理请求的响应结果。
updateStaffInfo
函数用于修改员工数据。它接收一个参数data
,该参数包含要更新的员工数据。在函数内部,它使用了httpRequest
模块来发起HTTP POST请求,请求的URL也是/staff
,并将data
作为请求的主体数据传递给请求。该函数同样返回一个Promise,用于处理请求的响应结果。
使用封装的useFetch
<template>
<div></div>
</template>
<script setup lang="ts">
import { getStaffInfoByPage } from "~/api/staff";
const getStaffInfo = async () => {
try {
await nextTick();
let res: any = await getStaffInfoByPage({
page: 1,
pageSize: 20,
});
console.log("员工信息", res.data);
} catch (error) {
console.log(error);
}
};
onMounted(() => {
getStaffInfo();
});
</script>
<style lang="scss" scoped></style>
注意: 浏览器刷新的时候页面没有显示数据,接口data无返回。本身nuxt的useFetch在参数不变的情况下,数据是不会重新从后台接口去请求数据的,会直接拿上一次的结果。但是有实时去后台获取数据这样的需求,
比如我的关注页面,在其他页面点了关注,每次进这个页面或者刷新都需要去后台重新获取数据,所以我给入参加了一个以时间戳为值的参数key,但是这样导致每次F5刷新页面的时候,都拿不到数据,导致页面没有显示。Suspense不起作用。
解决方法: 函数方法+await nextTick(),把获取数据接口放在方法里,方法里使用await nextTick(),然后调用方法.
可以把await nextTick一起封装在类中
import { UseFetchOptions } from "nuxt/app";
type Methods = "GET" | "POST" | "DELETE" | "PUT";
const BASE_URL = "http://127.0.0.1:8090";
export interface IResultData<T> {
code: number;
data: T;
msg: string;
}
class HttpRequest {
async request<T = any>(
url: string,
method: Methods,
data: any,
options?: UseFetchOptions<T>,
) {
await nextTick(); //解决刷新页面useFetch无返回
return new Promise((resolve, reject) => {
const newOptions: UseFetchOptions<T> = {
baseURL: BASE_URL,
method: method,
...options,
};
if (method === "GET" || method === "DELETE") {
newOptions.params = data;
}
if (method === "POST" || method === "PUT") {
newOptions.body = data;
}
useFetch(url, newOptions)
.then((res) => {
resolve(res);
})
.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);
}
Put<T = any>(url: string, data: any, options?: UseFetchOptions<T>) {
return this.request(url, "PUT", data, options);
}
Delete<T = any>(url: string, params: any, options?: UseFetchOptions<T>) {
return this.request(url, "DELETE", params, options);
}
}
const httpRequest = new HttpRequest();
export default httpRequest;