首页 > 其他分享 >【Nuxt3】使用内置方法获取网络数据和使用场景

【Nuxt3】使用内置方法获取网络数据和使用场景

时间:2024-03-29 17:59:12浏览次数:17  
标签:内置 请求 Nuxt3 useFetch 使用 useAsyncData fetch pending 客户端

简言

记录下如何使用useFetch和$fetch的使用方法和它们的使用场景。

获取数据

nuxt3内置了很多方法来获取网络数据。
这些方法有:

  • useAsyncData — useAsyncData 可以访问以 SSR 友好的可组合方式异步解析的数据。
  • useFetch — 使用 SSR 友好型可组合程序从 API 端点获取数据。
  • $fetch — Nuxt 使用 ofetch 在全局范围内公开 $fetch 辅助程序,用于执行 HTTP 请求。
  • useLazyAsyncData — 这个围绕 useAsyncData 的包装器会立即触发导航,useAsyncData的lazy为true版本。
  • useLazyFetch — 这个围绕 useFetch 的包装器会立即触发导航,useFetch的lazy为true版本。

主要是前三个常用,useAsyncData和$fetch结合使用可以在服务器端数据数据和水合,useFecth则是两者的语法糖,$fetch是客户端的http请求,获取数据后在客户端进行水合,后面两个看场景,需要立即导航时可以使用,

useAsyncData

在页面、组件和插件中,您可以使用 useAsyncData 来访问异步解析的数据。

useAsyncData 是一种可组合程序,可在 Nuxt 上下文中直接调用。它能返回反应式可合成数据,并处理将响应添加到 Nuxt 有效载荷的过程,这样就能将响应从服务器传递到客户端,而无需在页面水合时在客户端重新获取数据。

示例:

<script setup lang="ts">
const { data, pending, error, refresh } = await useAsyncData(
  'mountains',
  () => $fetch('https://api.nuxtjs.dev/mountains')
)
</script>

data、pending、status 和 error 是 Vue 的引用,在<script setup> 中使用时应使用 .value 进行访问,而 refresh/execute 是用于重新获取数据的普通函数。

参数

useAsyncData()可以接收三个参数:

  • key — 唯一的密钥,以确保在不同请求中正确地重复获取数据。如果不提供密钥,系统将为您生成与 useAsyncData 实例的文件名和行号唯一的密钥,建议添加
  • handler — 是一个异步函数,必须返回一个真实值(例如,不能是未定义的或空值),否则请求可能会在客户端被重复执行。
  • options — 配置选项对象,有以下属性:
    • server — 是否在服务器上获取数据(默认为 true)。
    • lazy — 是否在加载路由后解析异步函数,而不是阻止客户端导航(默认为 false)。
    • immediate — 设置为 false 时,将阻止请求立即触发。(默认为 true)。
    • default工厂函数,用于在异步函数解析前设置数据的默认值–在使用 lazy: true 或 immediate: false 选项时非常有用
    • transform — 函数,用于在解析后更改处理程序函数结果。
    • getCachedData — 提供一个返回缓存数据的函数。如果返回值为空或未定义,则会触发一次获取。默认情况下,这是:key => nuxt.isHydrating ? nuxt.payload.data[key] : nuxt.static.data[key],只有在启用 payloadExtraction 时才会缓存数据。
    • pick — 只从处理函数结果中选取数组中的指定键。
    • watch — 监视被动源自动刷新。
    • deep返回深度 ref 对象中的数据(默认为 true)。如果数据不需要深度反应,可以将其设置为 false,以浅层 ref 对象返回数据,这样可以提高性能
    • dedupe — 避免一次多次获取同一按键(默认为取消)。可选值有:
      • cancel — 在有新申请时取消现有申请。
      • defer —如果有悬而未决的请求,则根本不会提出新请求。

第三个参数,watch、default是常用的。

返回值

返回值是一个异步函数对象(Promise函数对象)。

  • data — 传入的异步函数的结果。

  • pending ---- 布尔值,表示是否仍在获取数据。

  • refresh/execute — 函数,用于刷新处理程序函数返回的数据。

  • error — 如果数据获取失败,则返回错误对象。

  • status ---- 表示数据请求状态的字符串(“idle”, “pending”, “success”, “error”)。

默认情况下,Nuxt 会等待刷新完成后才能再次执行。

示例

<script setup lang="ts">
/* Navigation will occur before fetching is complete.
  Handle pending and error states directly within your component's template
*/
const { pending, data: count } = await useAsyncData(
  "count",
  () => new Promise((resolve) => setTimeout(() => resolve(100), 1000)),
  {
    default: () => 0,
  }
);
console.log(pending.value);

watch(count, (newCount) => {
  // Because count might start out null, you won't have access
  // to its contents immediately, but you can watch it.
  console.log(newCount);
});
</script>

<template>
  <div>
    {{ pending ? "Loading" : count }}
  </div>
</template>

执行多个请求:

<script setup lang="ts">
const { data: discounts, pending } = await useAsyncData('cart-discount', async () => {
  const [coupons, offers] = await Promise.all([
    $fetch('/cart/coupons'),
    $fetch('/cart/offers')
  ])

  return { coupons, offers }
})
// discounts.value.coupons
// discounts.value.offers
</script>

$fetch

Nuxt 包含 ofetch 库,并作为 $fetch 别名在应用程序中全局自动导入。这也是 useFetch 在幕后使用的。

请注意,仅使用 $fetch 无法实现网络调用的重复删除和导航预防。
建议在客户端交互(基于事件)中使用 $fetch,或在获取初始组件数据时结合使用 useAsyncData。

在组件中使用 $fetch 而不使用 useAsyncData 对其进行包装会导致获取数据两次:最初在服务器上,然后在水合过程中再次在客户端,因为 $fetch 不会将状态从服务器传输到客户端。因此,由于客户端必须再次获取数据,因此获取将在两侧执行。

我们建议在获取组件数据时使用 useFetch 或 useAsyncData + $fetch 以防止重复获取数据。

== 上面说的组件其实是页面,也就是说如果是一个页面导航,建议使用useFetch,如果你的数据不触发导航调用,可以在事件中使用$fetch,因为那时候是客户端调用,不会触发服务端渲染 ==

您可以在任何仅在客户端执行的方法中使用 $fetch。

<script setup lang="ts">
function contactForm() {
  $fetch('/api/contact', {
    method: 'POST',
    body: { hello: 'world '}
  })
}
</script>

<template>
  <button @click="contactForm">Contact</button>
</template>

useFetch

该可组合程序为 useAsyncData 和 $fetch 提供了方便的封装。它根据 URL 和获取选项自动生成密钥,根据服务器路由为请求 url 提供类型提示,并推断 API 响应类型。

useFetch 是一种可组合程序,可在设置函数、插件或路由中间件中直接调用。它能返回反应式可组合程序,并将响应添加到 Nuxt 有效载荷中,以便从服务器传递到客户端,而无需在页面水合时在客户端重新抓取数据。

您还可以使用拦截器:

const { data, pending, error, refresh } = await useFetch('/api/auth/login', {
  onRequest({ request, options }) {
    // Set the request headers
    options.headers = options.headers || {}
    options.headers.authorization = '...'
  },
  onRequestError({ request, options, error }) {
    // Handle the request errors
  },
  onResponse({ request, response, options }) {
    // Process the response data
    localStorage.setItem('token', response._data.token)
  },
  onResponseError({ request, response, options }) {
    // Handle the response errors
  }
})

可以封装一个自定义请求方法,注意不要同名

参数

useFetch()接收三个参数:

  • url — 要获取的 URL。
  • Options1(扩展 unjs/ofetch 选项和 AsyncDataOptions)
    • method — 请求方法。
    • query — 使用ufo 在 URL 中添加查询搜索参数。
    • params — query的别名。
    • body — 请求正文(请求体),会自动字符串化(如果传递的是对象)。
    • headers — 请求标头。
    • baseURL — 请求的基本 URL。
    • timeout — 自动放弃请求的毫秒数。

所有获取选项都可以给出一个计算值或 ref 值。这些值一旦更新,就会受到监视,并自动使用任何新值发出新请求。

  • Options2 (来自 useAsyncData) — 这个选项就是useAsyncData的第一个参数 + 第三个参数 。

返回值

返回值和useAsyncData返回值类型相同。

function useFetch<DataT, ErrorT>(
  url: string | Request | Ref<string | Request> | () => string | Request,
  options?: UseFetchOptions<DataT>
): Promise<AsyncData<DataT, ErrorT>>

type UseFetchOptions<DataT> = {
  key?: string
  method?: string
  query?: SearchParams
  params?: SearchParams
  body?: RequestInit['body'] | Record<string, any>
  headers?: Record<string, string> | [key: string, value: string][] | Headers
  baseURL?: string
  server?: boolean
  lazy?: boolean
  immediate?: boolean
  getCachedData?: (key: string, nuxtApp: NuxtApp) => DataT
  deep?: boolean
  dedupe?: 'cancel' | 'defer'
  default?: () => DataT
  transform?: (input: DataT) => DataT | Promise<DataT>
  pick?: string[]
  watch?: WatchSource[] | false
}

type AsyncData<DataT, ErrorT> = {
  data: Ref<DataT | null>
  pending: Ref<boolean>
  refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
  execute: (opts?: AsyncDataExecuteOptions) => Promise<void>
  clear: () => void
  error: Ref<ErrorT | null>
  status: Ref<AsyncDataRequestStatus>
}

interface AsyncDataExecuteOptions {
  dedupe?: 'cancel' | 'defer'
}

type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'

示例

import type { UseFetchOptions, } from "#app"
import { defu } from 'defu'
import { MyHttpResponse } from '~/types/common'
import type { KeysOf, PickFrom, _AsyncData } from "nuxt/dist/app/composables/asyncData";
import type { FetchError, } from 'ofetch';
export async function useCustomFetch<T extends MyHttpResponse>(url: string | (() => string), options: UseFetchOptions<T> = {}): Promise<_AsyncData<PickFrom<T, KeysOf<T>> | null, FetchError<T> | null>> {
  const userAuth = useCookie('token').value
  const config = useRuntimeConfig()
  url = (config.public.apiBase || '/api') + url

  const defaults: UseFetchOptions<T> = {
    baseURL: config.public.apiBase as string ?? 'http:192.168.9.70:3000/api/', //  公共路径,
    key: url + Date.now(),
    headers: userAuth ?
      { Authorization: userAuth }
      : {},
    onResponse(_ctx) {

    },
    onResponseError(_ctx) {

    }
  }

  const params = defu(options, defaults)

  const res = await useFetch(url, params)

  return res
}
<script setup lang="ts">
const { data: count } = await useFetch('/api/count')
</script>

<template>
  <p>Page visits: {{ count }}</p>
</template>

注意!!!

useFetch()会在服务端请求数据然后水合,若请求失败会在客户端进行再次请求。
key值不同也会请求两次(服务端一次,客户端一次)。

如果是刷新(F5)则会触发服务端渲染并进行上述情况,不刷新页面触发vue-router导航,则只会进行客户端触发请求

另外,如果你想使用useFetch()获取请求后更新页面头部meta元数据,我的解决方法是:

  1. url的useFetch的url使用完整的http/https请求(http://.xxxx/xxx)这种,不完整的你查看页面源代码会发现区别。
  2. 然后key属性使用uuid或时间戳(解决f5刷新不会调用数据,不要 使用 await nextTick();)
  3. 正常使用即可。

这是我现在知道的唯一暂行方法,不知道原因,有知道其他方法的可以评论告诉我,谢谢。

在这里插入图片描述

useLazyAsyncData

默认情况下,useAsyncData 会阻止导航,直到其异步处理程序被解析。useLazyAsyncData 提供了一个围绕 useAsyncData 的包装器,通过将 lazy 选项设置为 true,可以在处理程序解析之前触发导航。

<script setup lang="ts">
/* Navigation will occur before fetching is complete.
  Handle pending and error states directly within your component's template
*/
const { pending, data: count } = await useLazyAsyncData('count', () => $fetch('/api/count'))

watch(count, (newCount) => {
  // Because count might start out null, you won't have access
  // to its contents immediately, but you can watch it.
})
</script>

<template>
  <div>
    {{ pending ? 'Loading' : count }}
  </div>
</template>

useLazyFetch

默认情况下,useFetch 会阻止导航,直到其异步处理程序解析完毕。useLazyFetch 提供了一个围绕 useFetch 的封装,通过将 lazy 选项设置为 true,可以在处理程序解析完毕之前触发导航。

<script setup lang="ts">
/* Navigation will occur before fetching is complete.
  Handle pending and error states directly within your component's template
*/
const { pending, data: posts } = await useLazyFetch('/api/posts')
watch(posts, (newPosts) => {
  // Because posts might start out null, you won't have access
  // to its contents immediately, but you can watch it.
})
</script>

<template>
  <div v-if="pending">
    Loading ...
  </div>
  <div v-else>
    <div v-for="post in posts">
      <!-- do something -->
    </div>
  </div>
</template>

结语

这些方法获取数据够用了,不建议额外使用axios或request等第三方请求库。

标签:内置,请求,Nuxt3,useFetch,使用,useAsyncData,fetch,pending,客户端
From: https://blog.csdn.net/qq_43231248/article/details/137146419

相关文章

  • JavaScript代码安全性提升:选择和使用JS混淆工具的指南
    引言在Web开发中,JavaScript是一种常用的脚本语言,然而,由于其代码容易被他人轻易获取和修改,为了保护JavaScript代码的安全性和版权,我们需要使用JS混淆工具。本文将介绍什么是JS混淆工具、为什么要使用以及如何选择合适的JS混淆工具,同时还会列举一些常用的JS混淆工具。 正文什......
  • 在使用PageHelper插件进行分页查询时,为什么在Postman进行后端测试时返回的data中对应
    注意:在使用PageHelper插件进行分页查询,由Postman进行后端测试时,需要根据返回的total(查询的总记录数)和测试设置的pageSize(每页记录条数)来设置page(查询页码)的值,否则后端测试返回的data中对应的rows可能为空。理由如下:假设此时是这样一个查询情景:通过动态SQL进行条件查询,......
  • 客快物流大数据项目(一百):ClickHouse的使用 spark操作ClickHouse代码
    ClickHouse的使用一、使用Java操作ClickHouse1、构建maven工程2、​​​​​​​导入依赖<!--Clickhouse--><dependency><groupId>ru.yandex.clickhouse</groupId><artifactId>clickhouse-jdbc</artifactId><version>0.2.2</v......
  • 【前端】- 在使用Element UI 的el-tree组件时,从底层去研究如何去实现一键展开/关闭【t
    第一步:首先我们先去查看elementui官方文档,发现并没有提供这个方法,没办法,只能手写一个了,先给大家看看功能点击前效果:点击后效果:第二步:废话不多说直接上代码,然后我们简单解释下代码页面部分:这里是简单的数结构渲染,不多讲,$refs.Reftree获取的是el-tree的实例,具体作用请看下......
  • lvgl移植以及使用记录(1)
    LVGL使用记录一、移植LVGL使用LVGL的V8.3.10版本,移植对照正点原子或者网上的教程。1.1移植部分打开LVGLPorting中lv_port_disp的宏,将if0改为if1,需要使用按键、旋转编码器、触摸屏则需要再打开lv_port_indev中的宏,配置好接口。(习惯先把屏幕调通,再去调其他组件)#if1......
  • 150. 如何使用 SAPGUI 中的树控件绘制树状数据结构
    大家在按照本文介绍的步骤进行学习之前,请务必先完成这两篇前置知识的学习:148.使用SAPGUI的Docking控件将屏幕划分成若干子区域149.如何在SAPGUI的ABAP报表里显示图片树形结构能够自然地表达层次化数据,如公司的组织架构、产品目录或项目任务的分解。在SA......
  • 【亚马逊云科技】使用 Vscode Amazon-Q 完成 GUI 界面粉笔脚本开发
    前言亚马逊云科技-Q,可以快速获得紧迫问题的相关答案,解决问题,生成内容。当与Q聊天时,它会提供即时的相关信息和建议,以帮助简化任务、加快决策速度,并帮助激发工作中的创造力和创新。本次我们通过完整的项目开发全方面体验一下Q的实用性,体验在代码开发中是否真正做到解放生产力......
  • 使用幸狐LuckFox Pico Plus 板子搭载Alpine Linux,运行dotnet net6程序 闪烁一颗LED灯
    程序截图 实拍 性能消耗非常小的,就是对ROM有要求,SDK+程序占了40M 步骤1:按照链接教程刷入系统步骤2:修改以太信息步骤3:使用ssh登录系统步骤4:搭建dotnet环境,使用手动的方式先下载运行时包下载.NET6.0Runtime(v6.0.28)-LinuxArm32AlpineBinaries(microsoft.co......
  • /dev/null和标准*使用
    "/dev/null"是一个特殊的设备文件,它在Unix和类Unix系统中用于丢弃数据或忽略输出。当数据被写入/dev/null时,实际上是将数据丢弃,而读取/dev/null则会立即返回文件结尾(EOF)。在Unix/Linux系统中,一切皆文件的思想也适用于设备。/dev/null是一个特殊的设备文件,它不对应任......
  • 【工具】navcat无限使用
    1.打开无限试用工具所在文件夹,打开navcat安装所在文件夹2.将破解dll文件移动到navcat安装目录下然后就去试用软件吧,如果软件试用到期了或者快要到期就运行这个脚本就行。按道理来说这个脚本运行一次就会自动帮你续期的......