Nuxt3封装网络请求 useFetch $fetch

前言:

刚接触、搭建Nuxt3项目的过程还是有点懵的,有种摸石头过河的感觉,对于网络请求这块,与之前的Vue3项目有所区别,在Vue项目通常使用axios这个库进行网络请求,但在Nuxt项目并不推荐,因为有内置 fetch 相关...接下来一起学习一下Nuxt3数据请求的点点滴滴吧~

文档:

数据获取 · 快速入门 Nuxt

关键:

  • useFetch 是在组件设置函数中处理数据获取的最简单方法。
  • $fetch 可以根据用户交互进行网络请求。
  • useAsyncData 结合 $fetch,提供了更精细的控制。

讲解:

useAsyncData:
  • 提供了一种在SSR友好的组合式中访问异步解析数据的方式
  • 注意,setup期间,这里结合了$fetch,并且设置了一个key,一个唯一的键,用于确保数据获取可以在请求中正确去重
  • <script setup>
    const { data, pending, error, refresh } = await useAsyncData(
      'mountains',
      () => $fetch('https://api.nuxtjs.dev/mountains')
    )
    </script>
  • 当 CMS 或第三方提供自己的查询层时。在这种情况下,您可以使用 useAsyncData 来封装您的调用,并仍然保持组合函数提供的好处。 
$fetch:
  • Nuxt使用 ofetch 来全局暴露`$fetch`辅助函数,用于在Vue应用程序或API路由中进行HTTP请求 
  • 源码:nuxt/packages/nuxt/src/app/entry.ts at main · nuxt/nuxt · GitHub
  • $fetch是在Nuxt中进行HTTP调用的首选方式,而不是为Nuxt 2设计的@nuxt/http和@nuxtjs/axios。
  • 比如,你的页面有给用户提供交互的(按钮),那么就可以使用 $fetch ,不然控制台会有警告,网上就有不少人是在交互的时候使用useFetch而出现问题,看下面这篇文章
  • 警告:[nuxt] [useFetch] Component is already mounted, please use $fetch instead. See https://nuxt.com/docs/getting-started/data-fetching
  • Nuxt 3:正确的方法 --- useFetch in Nuxt 3: The Proper Way (alex.party)
  • 请观察以下调用接口的时机:setup | click
  • <script setup lang="ts">
    // 在SSR中数据将被获取两次,一次在服务器端,一次在客户端。
    const dataTwice = await $fetch('/api/item')
    
    // 在SSR中,数据仅在服务器端获取并传递到客户端。
    const { data } = await useAsyncData('item', () => $fetch('/api/item'))
    
    // 你也可以使用useFetch作为useAsyncData + $fetch的快捷方式
    const { data } = await useFetch('/api/item')
    </script>
    <script setup lang="ts">
    function contactForm() {
      $fetch('/api/contact', {
        method: 'POST',
        body: { hello: 'world '}
      })
    }
    </script>
    
    <template>
      <button @click="contactForm">联系我们</button>
    </template>
useFetch :
  • 使用一个与SSR兼容的可组合函数从API端点获取数据。
  • 包装了useAsyncData和$fetch,它返回响应式的可组合函数,并处理将响应添加到Nuxt的负载中,以便在页面水合时可以从服务器传递给客户端,而无需在客户端重新获取数据。
  • (水合的概念在文档的渲染模式有讲解:渲染模式 · 关键概念 (nuxt.com.cn))
  • 提供了拦截器
  • const { data, pending, error, refresh } = await useFetch('/api/auth/login', {
      onRequest({ request, options }) {
        // 设置请求头
        options.headers = options.headers || {}
        options.headers.authorization = '...'
      },
      onRequestError({ request, options, error }) {
        // 处理请求错误
      },
      onResponse({ request, response, options }) {
        // 处理响应数据
        localStorage.setItem('token', response._data.token)
      },
      onResponseError({ request, response, options }) {
        // 处理响应错误
      }
    })
    
  • 事实上,useFetch(url) 几乎等同于 useAsyncData(url, () => $fetch(url)) - 它是为最常见的用例提供的开发者体验糖。 

封装:工厂函数设计请求代码结构

env:
  • 在nuxt.config.ts配置 runtimeConfig,通过useRuntimeConfig()解构,示例:
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      API_BASE_DEV: 'http://localhost:4000',
      API_BASE_PROD: 'https://api.example.com/v1'
    }
  },
})
  • 当然你还可以

 composables:
  • 封装$fetch
  • - composables/useDollarFetchRequest.ts
import { $fetch } from 'ofetch';
import { useRuntimeConfig } from '#app';

interface RequestOptions {
  customBaseURL?: string;
  [key: string]: any;
}

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

// 请求拦截器
function handleRequest(options: RequestOptions) {
  options.headers = {
    ...options.headers,
    'Content-Type': 'application/json',
  };
}

// 响应拦截器
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: {
        API_BASE_DEV,
        API_BASE_PROD
      }
    } = useRuntimeConfig();

    const baseURL = process.env.NODE_ENV === 'production'
      ? API_BASE_PROD
      : API_BASE_DEV;

    const requestUrl = new URL(
      url,
      options.customBaseURL || baseURL
    ).toString();

    try {
      handleRequest(options);
      const response = await $fetch(requestUrl, {
        method,
        body: data,
        ...options,
      });
      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');
  • 封装useFetch
  • - composables/useFetchRequest.ts
import { useFetch, useRuntimeConfig } from '#app';
import type { UseFetchOptions } from 'nuxt/app';

interface RequestOptions extends UseFetchOptions<any> {
  customBaseURL?: string;
}

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type HandleRequestOptions = { request: Request; options: RequestOptions };
type HandleResponseOptions = { response: any };

// 请求拦截器
function handleRequest({ options }: HandleRequestOptions) {
  options.headers = {
    ...options.headers,
    'Content-Type': 'application/json',
  };
}

// 响应拦截器
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: RequestOptions = {}
  ) {
    const {
      public: {
        API_BASE_DEV,
        API_BASE_PROD
      }
    } = useRuntimeConfig();

    const baseURL = process.env.NODE_ENV === 'production'
      ? API_BASE_PROD
      : API_BASE_DEV;

    const requestUrl = new URL(
      url,
      options.customBaseURL || baseURL
    ).toString();

    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');
统一管理 API 
  • 调用 $fetch 示例:
import { useDollarGet } from '~/composables/useDollarFetchRequest';

export const getDocsApi = () => useDollarGet('/docs/list');
<template>
    <div>
      <button @click="handleGetUserInfo">获取用户信息</button>
    </div>

    <HomeCover />
    <HomeIntro />
    <HomeCadre />
    <HomeJoinUs />
    <BackToTop />
</template>

<script setup lang="ts">
import HomeCover from './HomeCover.vue';
import HomeIntro from './HomeIntro.vue';
import HomeCadre from './HomeCadre.vue';
import HomeJoinUs from './HomeJoinUs.vue';
import { getDocsApi } from '../../api/home/joinUs';

const handleGetUserInfo = async () => {
  try {
    const data = await getDocsApi();
    console.log('文档列表:', data);
  } catch (error) {
    console.error('获取文档列表出错:', error);
  }
};
</script>
  • 调用 useFetch 示例
<script setup lang="ts">
import { getDocsApi } from '../../api/home/joinUs';

try {
  const response = await getDocsApi();
  console.log('文档列表:', response.data.value);
} catch (error) {
  console.error('获取文档列表出错:', error);
}

</script>
结果:

 


 欢迎三连,以及在评论区讨论,如果有不对的还请告知纠正 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/792987.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【PostgreSQL】Spring boot + Mybatis-plus + PostgreSQL 处理json类型情况

Spring boot Mybatis-plus PostgreSQL 处理json类型情况 一、前言二、技术栈三、背景分析四、方案分析4.1 在PostgreSQL 数据库中直接存储 json 对象4.2 在PostgreSQL 数据库中存储 json 字符串 五、自定义类型处理器5.1 定义类型处理器5.2 使用自定义类型处理器 一、前言 在…

【PowerShell】-1-快速熟悉并使用PowerShell

目录 PowerShell是什么&#xff1f;和CMD的区别&#xff1f; PowerShell的演变 自动化IT管理任务 一些名词 详尽的PowerShell开始之路 1.打开PowerShell&#xff1a; 2.基本命令&#xff1a; &#xff08;1&#xff09;Get-Process &#xff08;2&#xff09;变量赋值…

React Hooks学习笔记

一、usestate的使用方法-初始化state函数 import React, { useState } from "react"; function App() {const [count, setCount] useState(0);return (<div><p>点击{count}次</p><button onClick{() > setCount(count 1)}>点击</bu…

【Linux系统】信号量(初次理解)

五个概念 多个执行流&#xff08;进程&#xff09;&#xff0c;能看到的一份资源&#xff1a;共享资源被保护起来的资源可以叫临界资源&#xff08;同步和互斥&#xff09; --- 用互斥的方式保护共享资源就叫临界资源互斥&#xff1a;任何时刻只能有一个进程在访问共享资源资源…

就业平台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;企业管理&#xff0c;企业类型管理&#xff0c;留言板管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;招聘信息&#xff0c;简历&#xff0c;我的 …

SpringCloud--Eureka集群

Eureka注册中心集群 为什么要集群 如果只有一个注册中心服务器&#xff0c;会存在单点故障&#xff0c;不可以高并发处理所以要集群。 如何集群 准备三个EurekaServer 相互注册&#xff0c;也就是说每个EurekaServer都需要向所有的EureakServer注册&#xff0c;包括自己 &a…

游戏如何应对黑灰产工作室

游戏黑灰产工作室&#xff0c;是指以非法渠道、非法手段通过游戏进行牟利的团伙。使用脚本、外挂是黑灰产工作室的显著特征&#xff0c;其常见的牟利方式有&#xff1a;打金工作室、资源囤积号、初始号、自抽号、代练工作室以及营销欺诈等。 ▲ 常见的游戏黑灰产工作室牟利路径…

PMP证书 怎么报名?

首先&#xff0c;PMP证书相当于某些行业的敲门砖&#xff0c;身处项目管理相关行业的人应该清楚&#xff0c;这个证书&#xff0c;可能是你升职的不可或缺的一把钥匙。首先&#xff0c;我们先来了解一下什么是pmp。 1充分了解PMP PMP&#xff08;项目管理专业人士资格认证&am…

idm站点抓取可以用来做什么 idm站点抓取能抓取本地网页吗 idm站点抓取怎么用 网络下载加速器

在下载工具众多且竞争激烈的市场中&#xff0c;Internet Download Manager&#xff08;简称IDM&#xff09;作为一款专业的下载加速软件&#xff0c;仍然能够赢得众多用户的青睐&#xff0c;这都要得益于它的强大的下载功能。我们在开始使用IDM的时候总是有很多疑问&#xff0c…

「iOS」暑假第一周 —— ZARA的仿写

暑假第一周 ZARA的仿写 文章目录 暑假第一周 ZARA的仿写写在前面viewDidLoad 之中的优先级添加自定义字体下载想要的字体添加至info之中找到字体名字并应用 添加应用图标和启动页面 写在前面 暑假第一周留校学习&#xff0c;对于ZARA进行了仿写&#xff0c;在仿写的过程之中&a…

探索创意无限:独特的平面设计趋势与案例分享

随着平面设计领域的不断发展&#xff0c;平面设计趋势也在不断变化。在一个信息爆炸的时代&#xff0c;设计不仅仅是视觉的表达&#xff0c;更是思想和情感的交流。到了 2024 年&#xff0c;一些新的平面设计趋势已经开始显现&#xff0c;同时一些旧的趋势得到了新的发展和再度…

Jenkins安装部署与配置

目录 前言 Jenkins 的主要功能 Jenkins 的工作流程 一. 环境准备 二. 安装JDK 三. 安装Tomcat 四. 部署Jenkins 五. 浏览器访问 六. 修改超级管理员默认密码 七. 系统配置 八. 安装插件 九. 手动部署插件 前言 Jenkins 是一个开源的自动化服务器&#xff0c;用于…

C# 串口数据转网口实现空气风速风向检测

1.窗体搭建 添加time(定时器) 因为需要风速和风向自动刷新 2.进行网口空气检测 ①服务器连接按钮 // 连接按钮private void button1_Click(object sender, EventArgs e){if (button1.Text "连接"){ConnectSocke();// 连接服务器}else{CloseSocket(); // 关闭服务器…

苹果提出RLAIF:轻量级语言模型编写代码

获取本文论文原文PDF&#xff0c;请在公众号【AI论文解读】留言&#xff1a;论文解读 代码生成一直是一个充满挑战的领域。随着大型语言模型&#xff08;LLM&#xff09;的出现&#xff0c;我们见证了在自然语言理解和生成方面的显著进步。然而&#xff0c;当涉及到代码生成&a…

XD文件打开神器:这个在线工具你一定要试试!

你有没有遇到过对设计师发来的XD文件没有头绪&#xff1f;不知道XD文件深层含义&#xff1f;如何打开XD文件最省时省力&#xff1f;这篇文章告诉你答案。 https://ad.js.design/online/xd/?sourcecsdn&planxy711 XD文件是什么&#xff1f; 事实上&#xff0c;XD文件就是…

C++入门基础篇(1)

欢迎大家来到海盗猫鸥的博客—— 断更许久&#xff0c;让我们继续好好学习吧&#xff01; 目录 1.namespace命名空间 命名空间的存在价值&#xff1a; 命名空间的定义&#xff1a; 命名空间的使用&#xff1a; 2.C输入输出函数 使用&#xff1a; 3.缺省参数 4.函数重载…

界面组件Kendo UI for React 2024 Q2亮点 - 生成式AI集成、设计系统增强

随着最新的2024年第二季度发布&#xff0c;Kendo UI for React为应用程序开发设定了标准&#xff0c;包括生成式AI集成、增强的设计系统功能和可访问的数据可视化。新的2024年第二季度版本为应用程序界面提供了人工智能(AI)提示&#xff0c;从设计到代码的生产力增强、可访问性…

linux-5.10.110内核源码分析 - Freescale ls1012a pcie msi中断

1、dts msi控制器描述 1.1、dts描述 msi: msi-controller11572000 {compatible "fsl,ls1012a-msi";reg <0x0 0x1572000 0x0 0x8>;msi-controller;interrupts <0 126 IRQ_TYPE_LEVEL_HIGH>; };ls1012a msi控制器具体介绍可以参考官网手册”25.1.1 PC…

【cocos creator】2.x,伪3d拖拽,45度视角,60度视角,房屋装扮

伪3d拖拽,45度视角,60度视角 工程下载:(待审核) https://download.csdn.net/download/K86338236/89530812 dragItem2.t s import mapCreat2 from "./mapCreat2";const {ccclass, property } = cc._decorator; /*** 拖拽类,挂在要拖拽的节点上*/ @ccclass export…

电影购票小程序论文(设计)开题报告

一、课题的背景和意义 随着互联网技术的不断发展&#xff0c;人们对于购票的需求也越来越高。传统的购票方式存在着排队时间长、购票流程繁琐等问题&#xff0c;而网上购票则能够有效地解决这些问题。电影购票小程序是网上购票的一种新型应用&#xff0c;它能够让用户随时随地…