Nuxt3封装网络请求 useFetch & $fetch

06-01 1049阅读

前言:

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

文档:

数据获取 · 快速入门 Nuxt

关键:

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

    讲解:

    useAsyncData:
    • 提供了一种在SSR友好的组合式中访问异步解析数据的方式
    • 注意,setup期间,这里结合了$fetch,并且设置了一个key,一个唯一的键,用于确保数据获取可以在请求中正确去重
    • const { data, pending, error, refresh } = await useAsyncData(
        'mountains',
        () => $fetch('https://api.nuxtjs.dev/mountains')
      )
      
    • 当 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
      • // 在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')
        
        function contactForm() {
          $fetch('/api/contact', {
            method: 'POST',
            body: { hello: 'world '}
          })
        }
        
        
          联系我们
        
        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'
                }
              },
            })
            • 当然你还可以

              Nuxt3封装网络请求 useFetch & $fetch

               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 {
                    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');
                    
                        
                          获取用户信息
                        
                        
                        
                        
                        
                        
                    
                    
                    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);
                      }
                    };
                    
                    
                    • 调用 useFetch 示例
                      import { getDocsApi } from '../../api/home/joinUs';
                      try {
                        const response = await getDocsApi();
                        console.log('文档列表:', response.data.value);
                      } catch (error) {
                        console.error('获取文档列表出错:', error);
                      }
                      
                      结果:

                      Nuxt3封装网络请求 useFetch & $fetch

                      Nuxt3封装网络请求 useFetch & $fetch 


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

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码