Skip to content

Nuxt3 请求知识点

三种方式

  • $fetch

  • useAsyncData

  • useFetch

$fetch

  • $fetch 没有任何的缓存

使用场景

  • setup 顶部

CAUTION

$fetch 顶部使用的时候没有任何缓存,会向服务器发送两次请求,一次是服务器端,一次是客户端

  • 事件

CAUTION

$fetch 只发送一次请求,不用渲染

封装

  • 在 composables 文件夹下面 新建一个 use$fetch.ts 文件
ts
interface RequestOptions {
  [key: string]: any;
}

type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";

// 请求拦截器
function handleRequest(options: RequestOptions) {
  options.headers = {
    ...options.headers,
    "Content-Type": "application/json",
    token: unref(useCookie("token")),
    sign: "123987",
  };
}

// 响应拦截器
function handleResponse(response: any) {
  if (response.error) {
    throw new Error(response.error.message || "响应错误");
  }
  return response;
}

/**
 * 创建请求方法
 * @param method
 */
function createDollarFetchRequest(method: HttpMethod) {
  return async function (
    url: string,
    data?: any,
    options: RequestOptions = {}
  ) {
    const {
      public: { baseURL },
    } = useRuntimeConfig();

    const requestUrl = baseURL + url;

    try {
      handleRequest(options);
      if (method == "GET") {
        const response = await $fetch(requestUrl, {
          method,
          query: data,
          key: JSON.stringify(Math.random() * 100),
          ...options,
          onRequest() {
            console.log("GET拦截器");
          },
        });
        return handleResponse(response);
      } else {
        const response = await $fetch(requestUrl, {
          method,
          body: data,
          ...options,
          onRequest() {
            console.log("POST拦截器");
          },
        });
        return handleResponse(response);
      }
    } catch (error) {
      console.error("请求错误:", error);
      throw error;
    }
  };
}

// 提供 $fetch & HTTP 方法 - 统一管理请求 - 再到组件中使用
export const useDollarGet = createDollarFetchRequest("GET");
export const useDollarPost = createDollarFetchRequest("POST");
export const useDollarPut = createDollarFetchRequest("PUT");
export const useDollarDelete = createDollarFetchRequest("DELETE");

使用

ts
import { useDollarGet, useDollarPost } from "~/composables/use$fetch";

const get1 = (params: any) => {
  console.log(params);
  return useDollarGet("/get1", params, { pick: ["data"] });
};

const post1 = (params: any) => {
  return useDollarPost("/testrouter1", params, { pick: ["data"] });
};
export default {
  get1,
  post1,
};

组件里面用

ts
// ApiALL 就是上面那个文件 通过import * as ApiAll from "~/composables/use$fetch";引入
let postmessage2 = ref("");
const result1 = await ApiAll.get1({ id: "呵呵呵" }).catch((e) => {
  navigateTo("/404");
});
postmessage2.value = result1.data;

useAsyncData

有缓存机制,当你的参数不变,路径不变,请求的时候只发送一次

使用场景

一般用于页面一开始获取数据,useAsyncData 与$fetch 一起使用,适用于多个接口

使用

  • 组件里面
ts
const { data } = await useAsyncData("/api/getdata2", async () => {
  const result = await Promise.all([
    ApiAll.get1({ id: "呵呵呵4232" }),
    ApiAll.post1({
      id: "Post数据6999",
    }),
  ]).catch((e) => {
    return {
      code: 500,
      message: e.toString(),
    };
  });
  if (result.code == 500) {
    // 异常处理
    return result;
  } else {
    // 正确返回值
    return {
      getdata: result[0].data,
      postdata: result[1],
    };
  }
});

// 这里一定要判断下data 的值
if (!unref(data).getdata) {
  navigateTo("/404");
}
  • 这样请求后 你是看不到发送的请求的,因为他有缓存,他少发一次请求,客户端不在发送

如果你非要看见请求

  • 只有每次清空缓存
ts
clearNuxtData(); // 加上他 清除缓存走了2次
const { data } = await useAsyncData("/api/getdata2", async () => {
  const result = await Promise.all([
    ApiAll.get1({ id: "呵呵呵4232" }),
    ApiAll.post1({
      id: "Post数据6999",
    }),
  ]).catch((e) => {
    return {
      code: 500,
      message: e.toString(),
    };
  });
  console.log(result);
  if (result.code == 500) {
    // 异常处理
    return result;
  } else {
    // 正确返回值
    return {
      getdata: result[0].data,
      postdata: result[1],
    };
  }
});
// 这里一定要判断下data 的值
if (!unref(data).getdata) {
  navigateTo("/404");
}

useFetch

有缓存机制,并且他给封装好数据.动态监听(这点最恶心)

比如一个输入框,当你不停的输入的时候,他会自己不停的发送请求,并且你看到请求的参数一直在变

个人不推荐.一般用$fetch

使用场景

一般用于事件触发

使用

  • 封装 useFetch
ts
/*
 * @Author: jsopy
 * @Date: 2024-10-18 06:48:36
 * @LastEditTime: 2024-10-18 13:30:18
 * @FilePath: /demo1/composables/useFectchRequest.ts
 * @Description:
 *
 */
import type { UseFetchOptions } from "nuxt/app";

type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type HandleRequestOptions = { request: Request; options: UseFetchOptions<any> };
type HandleResponseOptions = { response: any };

// 请求拦截器
function handleRequest({ options }: HandleRequestOptions) {
  options.headers = {
    ...options.headers,
    "Content-Type": "application/json",
    token: unref(useCookie("token")),
    sign: "6666",
  };
}

// 响应拦截器
function handleResponse({ response }: HandleResponseOptions) {
  if (response._data.error) {
    throw new Error(response._data.error.message || "响应错误");
  }
  return response._data;
}

/**
 * 创建请求方法
 * @param method
 */
function createUseFetchRequest(method: HttpMethod) {
  return async function (
    url: string,
    data?: any,
    options: UseFetchOptions<any> = {}
  ) {
    const {
      public: { baseURL },
    } = useRuntimeConfig();

    const requestUrl = baseURL + url;
    if (method == "GET") {
      return await useFetch(requestUrl, {
        ...options,
        method,
        query: data,
        onRequest: handleRequest,
        onResponse: handleResponse,
      });
    } else {
      return await useFetch(requestUrl, {
        ...options,
        method,
        body: data,
        onRequest: handleRequest,
        onResponse: handleResponse,
      });
    }
  };
}

// 提供 useFetch & HTTP 方法 - 统一管理请求 - 再到组件中使用
export const useFetchGet = createUseFetchRequest("GET");
export const useFetchPost = createUseFetchRequest("POST");
export const useFetchPut = createUseFetchRequest("PUT");
export const useFetchDelete = createUseFetchRequest("DELETE");
  • 剩下的步骤和前面封装的$fetch 一样使用