【nuxt3】优雅地封装useFetch

什么是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类型。这个对象包含了baseURLmethod两个属性,baseURL被设置为我们之前定义的BASE_URL常量,method被设置为传入的请求方法。

接下来,我们根据请求方法的不同,决定如何处理请求的数据。如果请求方法是GETDELETE,我们将数据设置为newOptionsparams属性;如果请求方法是POSTPUT,我们将数据设置为newOptionsbody属性。

我们使用useFetch函数来发送请求,该函数接受请求的路径和选项对象作为参数,并返回一个 Promise 对象。当请求成功时,我们将结果通过resolve方法传递出去;当请求失败时,我们通过reject方法将错误抛出。

紧接着,我们定义了一系列封装的常用方法:getpostputdelete。这些方法分别对应于 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;

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYEoIKGf' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片