当前位置:网站首页>[Nuxt 3] (七)获取数据
[Nuxt 3] (七)获取数据
2022-07-21 11:31:00 【choukin】
获取
Nuxt 内置了 useFetch
, useLazyFetch
, useAsyncData
, useLazyAsyncData
来处理应用程序的数据获取。
useFetch
, useLazyFetch
, useAsyncData
和 useLazyAsyncData
只能在 setup
or Lifecycle Hooks
中使用
useFetch
在你的页面、组件和插件中,您可以使用 useFetch
请求任何URL,
这个组合是对 useAsyncData
和 $fetch
的封装,它根据URL和 请求的参数自动生成密钥,并推断API的返回类型。
::ReadMore{link="/api/composables/use-fetch"} ::
例子:
<script setup>
const { data: count } = await useFetch('/api/count')
</script>
<template>
Page visits: {{ count }}
</template>
:LinkExample{link="/examples/composables/use-fetch"}
useLazyFetch
这个组合等价于 设置了 lazy:true
的 useFetch
,也就是这个异步函数不会阻塞导航,这意味着你需要处理数据为 null
的情况,(或者在工厂函数中自定义默认值)。
::ReadMore{link="/api/composables/use-lazy-fetch"} ::
例子:
<template>
<!-- you'll need to handle a loading state -->
<div v-if="pending">
Loading ...
</div>
<div v-else>
<div v-for="post in posts">
<!-- do something -->
</div>
</div>
</template>
<script setup>
const { pending, data: posts } = useLazyFetch('/api/posts')
watch(posts, (newPosts) => {
// Because posts starts out null, you won't have access
// to its contents immediately, but you can watch it.
})
</script>
useAsyncData
在页面,组件和插件中,你可以通过 useAsyncData
访问异步解析的数据。
你可能会疑惑:useFetch
和 useAsyncData
的区别是什么? 简单的说,useFetch
接收一个URL作为参数来获取数据,而useSyncData
可能具有更多的逻辑。 useFetch(url)
等同于 useAsyncData(url,()=>$fetch(url))
- 通常情况下,有利于开发体验。
::ReadMore{link="/api/composables/use-async-data"} ::
例子
let counter = 0
export default () => {
counter++
return JSON.stringify(counter)
}
<script setup>
const { data } = await useAsyncData('count', () => $fetch('/api/count'))
</script>
<template>
Page visits: {{ data }}
</template>
:LinkExample{link="/examples/composables/use-async-data"}
useLazyAsyncData
这个组合函数等价于,设置了 lazy:true
的useAsyncData
. 换句话说,这个异步函数不会阻塞导航,着意味着你需要处理 data 为 null
的情况,(或者在工厂函数中自定义默认值)。
::ReadMore{link="/api/composables/use-lazy-async-data"} ::
例子:
<template>
<div>
{{ pending ? 'Loading' : count }}
</div>
</template>
<script setup>
const { pending, data: count } = useLazyAsyncData('count', () => $fetch('/api/count'))
watch(count, (newCount) => {
// Because count starts out null, you won't have access
// to its contents immediately, but you can watch it.
})
</script>
刷新数据
有时,用户在浏览页面的过程中,你可以能要刷新从API加载的数据,比如用户在选择分页,过滤结果,搜索等等情况。
你可以使用refresh()
方法 来刷新 useFetch()
中根据不同参数返回的数据。
<script setup>
const page = ref(1);
const { data: users, pending, refresh, error } = await useFetch(() => `users?page=${page.value}&take=6`, { baseURL: config.API_BASE_URL }
);
function previous(){
page.value--;
refresh();
}
function next() {
page.value++;
refresh();
}
</script>
这里的关键是,修改 useFetch()
使用的参数后调用refresh()
refreshNuxtData
想要让 useAsyncData
useLazyAsyncData
useFetch
useLazyFetch
的缓冲失效,并触发重新请求。
当你想要刷新当前页面所有的数据时,可以使用这个方法。
::ReadMore{link="/api/utils/refresh-nuxt-data"} ::
例如:
<template>
<div>
{{ pending ? 'Loading' : count }}
</div>
<button @click="refresh">Refresh</button>
</template>
<script setup>
const { pending, data: count } = useLazyAsyncData('count', () => $fetch('/api/count'))
const refresh = () => refreshNuxtData('count')
</script>
同构 fetch
和 $fetch
当我们在浏览器中调用 fetch
时,像cookie
这样的用户header 信息会直接发送给API,但是当服务端渲染时,,由于fetch
请求时在服务端内部,因此它不包括用户浏览器端的cookies,也不从fetch响应传递cookie。
::ReadMore{link="/api/utils/$fetch"} ::
例子: 给API发送header 信息
我们可以使用 useRequestHeaders
从服务端访问并代理cookie给API
下面的例子将请求header 信息添加到同构的$fetch
调用中,来确保API端可以访问由用户端发送来的 cookie
.
<script setup>
const { data } = await useFetch('/api/me', {
headers: useRequestHeaders(['cookie'])
})
</script>
在将header代理到外部APi前要小心使用,只包含你需要的头部信息, 不是所有的header信息都可以安全传递,也有可能引起不确定的问题。
下面列出了常见的不需要代理的header信息。
host
,accept
content-length
,content-md5
,content-type
x-forwarded-host
,x-forwarded-port
,x-forwarded-proto
cf-connecting-ip
,cf-ray
例子: 在服务端API调用时,传递Cookie
如果你想要从内部请求向客户端传递或者代理 cookie,你需要自己处理这种情况
export const fetchWithCookie = async (url: string, cookieName: string) => {
const response = await $fetch.raw(url)
if (process.server) {
const cookies = Object.fromEntries(
response.headers.get('set-cookie')?.split(',').map((a) => a.split('='))
)
if (cookieName in cookies) {
useCookie(cookieName).value = cookies[cookieName]
}
}
return response._data
}
<script setup lang="ts">
// This composable will automatically pass on a cookie of our choice.
const result = await fetchWithCookie("/api/with-cookie", "test")
onMounted(() => console.log(document.cookie))
</script>
最佳实践
这些组合项返回的数据会被存储在页面负载内,这意味着返回的每个未在组件中使用的key 都会被添加到负载中。
我们强烈建议你,只选择组件中用到的key.
加入 /api/mountains/everest
返回下面的对象:
{
"title": "Mount Everest",
"description": "Mount Everest is Earth's highest mountain above sea level, located in the Mahalangur Himal sub-range of the Himalayas. The China–Nepal border runs across its summit point",
"height": "8,848 m",
"countries": [
"China",
"Nepal"
],
"continent": "Asia",
"image": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Everest_kalapatthar.jpg/600px-Everest_kalapatthar.jpg"
}
如果你只打算在你的组件中使用title
description
你可以通过$fetch
或者 pick
链式调用 选出你想要的key:
<script setup>
const { data: mountain } = await useFetch('/api/mountains/everest', { pick: ['title', 'description'] })
</script>
<template>
<h1>{{ mountain.title }}</h1>
<p>{{ mountain.description }}</p>
</template>
使用异步 setup
如果你想使用async setup()
,当前的组件实力会在第一个await
后消失,(这是Vue3的限制)如果你想使用多个异步操作,比如多次调用 useFetch
,你会需要使用 <script setup>
或者在setup末尾等待它们一起执行。
推荐使用<script setup>
它避免了顶层使用await的限制,阅读更多[1].
<script>
export default defineComponent({
async setup() {
const [{ data: organization }, { data: repos }] = await Promise.all([
useFetch(`https://api.github.com/orgs/nuxt`),
useFetch(`https://api.github.com/orgs/nuxt/repos`)
])
return {
organization,
repos
}
}
})
</script>
<template>
<header>
<h1>{{ organization.login }}</h1>
<p>{{ organization.description }}</p>
</header>
</template>
直接调用API
在某些情况下,你可能需要直接调用API,Nuxt3提供了一个全局可用的$fetch
方法,该方法使用unjs/ohmyfetch[2](除fetch
外),它的API和原生fetch[3]一样。
$fetch
有如下优点: 在服务器端它会智能得处理直接调用API,如果运行在客户端,它会对你的API进行调用,(它还可以处理调用第三方API) 此外,它还具有方便的功能,例如自动解析响应和字符串化数据。
参考资料
Vue setup: https://vuejs.org/api/sfc-script-setup
[2]ohmyfetch: https://github.com/unjs/ohmyfetch
[3]fetch: https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
边栏推荐
- 【CCF CSP】201512-1数位之和
- PWN的学习
- xxl-job(2.3.0)分布式任务bean模式,GLUE shell调度实践,源码debug
- Chapter III after class exercises 24-33
- 薅羊毛的最高境界,解放你的双手
- The highest state of pulling wool, liberate your hands
- Collation of common tools in commons Lang
- Monai label -- use AI to accelerate your segmentation annotation
- 第三方之百度AI使用总结
- 【CCF CSP】201609-1最大波动
猜你喜欢
论文阅读:CTRL: A CONDITIONAL TRANSFORMER LANGUAGE MODEL FOR CONTROLLABLE GENERATION
Natural language Processing in tensorflow quizs on Coursera
Paper reading: a large scale Chinese short text conversation dataset (cdial GPT)
一款免费听音乐和下载的播放器
Shell operators - mathematical operations, relational operations, string operations, file detection operations
残差网络解决了什么,为什么有效?—摘要
Countdownlatch, cyclicbarrier, semaphore of concurrent programming
马斯克自称大脑上云,是科学还是骗术?
Yan Weimin Chapter II after class exercises (2.29-2.38)
攻防世界新手区pwn
随机推荐
第三方之百度AI使用总结
5.2访问控制
合并二叉树
PWN的学习
重入读写锁ReentrantReadWriteLock特性总结
nexus管理页面上传jar,jar可以被正常拉取到项目,使用idea lifecycle的deploy发布的jar只能拉取到pom,401问题
Collation of common tools in commons Lang
【CCF CSP】201403-1相反数
[CCF CSP] 201604-1 break point count
[CCF CSP] 201612-1 median
使用sql批量修改MacOs照片应用(Photos)上的照片时间
【CCF CSP】201312-1出现次数最多的数
Hutool tool classes and tool methods
Monai label installation process and use strategy
【CCF CSP】201812-1小明上学
Web
【CCF CSP】201903-1小中大
Application of stack
[CCF CSP] 201312-1 the number with the most occurrences
Image text cross modal fine-grained semantic alignment confidence correction mechanism aaai2022