Nuxt3【网络请求】获取数据详解(2024最新版)

$fetch

Nuxt 中进行HTTP调用的首选方式

const users = await $fetch('/api/users').catch((error) => error.data)

缺陷:不会提供网络请求重复和导航阻止

<script setup lang="ts">
// 在SSR中数据将被获取两次,一次在服务器端,一次在客户端。
const dataTwice = await $fetch('/api/item')
</script>

适用场景:

  • 提交数据到事件处理程序

  • 在客户端逻辑中使用

    <script setup lang="ts">
    function contactForm() {
      $fetch('/api/contact', {
        method: 'POST',
        body: { hello: 'world '}
      })
    }
    </script>
    
    <template>
      <button @click="contactForm">联系我们</button>
    </template>
    
  • 与 useAsyncData 结合使用

    // 在SSR中,数据仅在服务器端获取并传递到客户端。
    const { data } = await useAsyncData('item', () => $fetch('/api/item'))
    

专用的组合式函数

为了避免重复的网络请和实现导航阻止,Nuxt 提供了专门的组合式函数来进行网络请求。

useAsyncData

const { data, error } = await useAsyncData('users', () => myGetFunction('users'))

第一个参数是用于缓存第二个参数(查询函数)的响应的唯一键,若第一个参数就传入函数,则唯一键会自动生成

useAsyncData 使用唯一键来防止重新获取相同的数据。( 使用 useNuxtData 可根据键获取缓存的数据 )

建议始终创建自己的键以避免不需要的行为

useAsyncData 是等待多个请求的绝佳方式。

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

    return {
      coupons,
      offers,
    };
  }
);

useFetch

可看作 useAsyncData + $fetch 的快捷方式

useFetch 使用 URL 或 选项中提供的 key 值作为唯一键来防止重新获取相同的数据。( 使用 useNuxtData 可根据键获取缓存的数据 )

const { data: count } = await useFetch('/api/count')

不适合的场景:

  • CMS 或第三方提供自己的查询层时 (此时建议用 useAsyncData)

懒加载(先导航)lazy

组合函数默认会等待数据请求完成后,再执行导航

通过 lazy 选项可以改为先导航,此时需使用pending值手动处理加载状态

<script setup lang="ts">
const { pending, data: posts } = useFetch('/api/posts', {
  lazy: true
})
</script>

<template>
  <!-- 你需要处理加载状态 -->
  <div v-if="pending">
    加载中...
  </div>
  <div v-else>
    <div v-for="post in posts">
      <!-- 做一些操作 -->
    </div>
  </div>
</template>

使用 useLazyFetch 和 useLazyAsyncData 可更方便地相同的操作。

const { pending, data: posts } = useLazyFetch('/api/posts')

仅在客户端获取数据 server

组合函数默认在客户端和服务器环境中都会执行异步函数。

将 server 选项设置为 false,则只在客户端执行调用。

与 lazy 选项结合使用,特别适合首次渲染不需要的数据(例如,非SEO敏感数据)

/* 此调用仅在客户端执行 */
const { pending, data: posts } = useFetch('/api/comments', {
  lazy: true,
  server: false
})

useFetch组合函数用于在设置方法中调用,或在生命周期钩子函数的函数顶层直接调用,否则你应该使用 $fetch 方法。

限定返回字段 pick

/* 仅选择模板中使用的字段 */
const { data: mountain } = await useFetch('/api/mountains/everest', { pick: ['title', 'description'] })

pick 不会阻止初始时获取不需要的数据,但会阻止不需要的数据被添加到从服务器传输到客户端的 html 中,从而减少有效负载大小

修改查询结果 transform

const { data: mountains } = await useFetch("/api/mountains", {
  transform: (mountains) => {
    return mountains.map((mountain) => ({
      title: mountain.title,
      description: mountain.description,
    }));
  },
});

transform 不会阻止初始时获取不需要的数据,但会阻止不需要的数据被添加到从服务器传输到客户端的 html 中,从而减少有效负载大小

刷新数据 refresh

请使用组合函数提供的 refresh 函数

<script setup lang="ts">
const { data, error, execute, refresh } = await useFetch('/api/users')
</script>

<template>
  <div>
    <p>{{ data }}</p>
    <button @click="refresh">刷新数据</button>
  </div>
</template>

execute函数是 refresh 的别名,使用方式完全相同,但在非立即的情况下更语义化。

刷新所有数据 refreshNuxtData

<script setup lang="ts">
const refreshing = ref(false)
const refreshAll = async () => {
  refreshing.value = true
  try {
    await refreshNuxtData()
  } finally {
    refreshing.value = false
  }
}
</script>

<template>
  <div>
    <button :disabled="refreshing" @click="refreshAll">
      重新获取所有数据
    </button>
  </div>
</template>

刷新特定数据

如:只刷新与 count 键匹配的数据

<script setup lang="ts">
  const { pending, data: count } = await useLazyAsyncData('count', () => $fetch('/api/count'))
  const refresh = () => refreshNuxtData('count')
</script>

<template>
  <div>
    {{ pending ? '加载中' : count }}
  </div>
  <button @click="refresh">刷新</button>
</template>

监听刷新 watch

使用 watch 选项,监听一个或多个响应式值,当其更改时重新运行获取函数

const id = ref(1)

const { data, error, refresh } = await useFetch('/api/users', {
  /* 更改id将触发重新获取 */
  watch: [id]
})

监视响应式值不会更改获取的URL。

动态 URL

随响应式值变化的 URL在每次更改时都会重新获取数据

const id = ref(null)

const { data, pending } = useLazyFetch('/api/user', {
  query: {
    user_id: id
  }
})

与非立即结合使用,可以在响应元素更改之前等待获取。

<script setup lang="ts">
const id = ref(null)

const { data, pending, status } = useLazyFetch(() => `/api/users/${id.value}`, {
  immediate: false
})
</script>

<template>
  <div>
    <!-- 在获取期间禁用输入 -->
    <input v-model="id" type="number" :disabled="pending"/>

    <div v-if="status === 'idle'">
      输入用户ID
    </div>
    
    <div v-else-if="pending">
      加载中...
    </div>

    <div v-else>
      {{ data }}
    </div>
  </div>
</template>

阻止立即执行 immediate: false

默认组合函数会立即开始获取数据,通过设置 immediate: false 可阻止立即执行

此时需要使用 status 来处理获取生命周期,并使用 execute 来开始数据获取。

<script setup lang="ts">
const { data, error, execute, pending, status } = await useLazyFetch('/api/comments', {
  immediate: false
})
</script>

<template>
  <div v-if="status === 'idle'">
    <button @click="execute">获取数据</button>
  </div>

  <div v-else-if="pending">
    加载评论中...
  </div>

  <div v-else>
    {{ data }}
  </div>
</template>

status 变量可能的取值有:

  • idle:获取未开始
  • pending:获取已开始但尚未完成
  • error:获取失败
  • success:获取成功完成

清除缓存数据 clearNuxtData

可删除 useAsyncData 和 useFetch的缓存数据、错误状态和待处理的 promises,用于使另一个页面的数据获取失效

参数为键,如果没有提供键,将会使所有数据失效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朝阳39

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值