Nuxt3 useFetch和$fetch的探讨以及封装请求处理
探讨
nuxt3采用了Hydration水合这样一个概念,用于处理服务端生成静态html与客户端js脚本的结合,实现一个可动态交互的页面应用,这个过程被称之为水合。
水合的过程可能会相对复杂一些,需要考虑到脚本加载、DOM的匹配、交互的激活(事件)、状态管理等等。
其中状态的管理,我目前使用的时候,发现它并不是理想中的那种状态。
理想中可能是:
服务端渲染时发起了一个api请求,获得了用户的数据,此时我们会将其存储到状态管理中,比如pinia之类的,然后客户端获取到服务端返回的数据,然后自己将pinia的数据恢复到内存中,如果使用了持久化存储,应该会自己将其存储到local之中。
但是,实际情况是,如果你想持久化,那你就必须自己在客户端的时候手动存储,也就是说,在服务端拿到的数据,哪怕你确实在代码中写了持久化处理,也是无效的,目前最佳实践就是在onMounted
中处理pinia的数据存储。
如果想在服务端拿到状态,我们还是需要使用到cookie。
除了状态管理,最复杂的其实是请求的处理,nuxt提供了好几种请求的方法。
useAsyncData
用于在水合时包装请求体,通过参数key唯一标识,减少服务端与客户端重复请求;$fetch
用于实际发起请求的方法,类似与axios,基于ofetch库的封装;useFetch
是将useAsyncData和$fetch
封装后的方法,减少每次都手动输入key做唯一标识的麻烦步骤,效果等同于useAsyncData和$fetch
的组合;useLazyAsyncData
用于在水合时不阻断页面的加载展示,比如你有一个b页面,在b页面的setup中就发起了useFetch请求,如果请求需要10s,那么用户就需要等到10s数据获取后,b页面才会进入并展示,如果使用useLazyAsyncData配合$fetch,就会直接进入页面,等数据获取后再渲染对应的dom元素;useLazyFetch
等同于useLazyAsyncData和$fetch的组合;
虽然说useAsyncData这种,通过key可以减少重复请求,那么useFetch也是一样的,但是实际上却略有不同?
<script lang="ts" setup>
const { data, error } = await useFetch("/xxxx", {
onResponse() {
console.log(1);
}
});
</script>
当页面第一次加载的时候,服务端生成html,此时就会就会触发useFetch
,但是当客户端渲染时,也会触发一次请求,这次请求不会出现在浏览下开发者控制台Network里面,但是响应拦截器onResponse
会被触发两次,你会在控制台看到log的两次打印。
于是我去查看了服务器的日志,api请求确实只发起了一次,由此我初步判定是拦截器会被运行两次,所以大伙使用上可能需要注意下,如果在这里做计数处理,可能是不准的。
由于这种情况,可能会导致像我一样,认为首次页面的请求会触发两次,导致认为useAsyncData
根本没啥作用。
但是如果你直接使用$fetch
去请求,是真的会触发两次,一次在服务器,一次在客户端。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
全部评论 98
上得分
Google Chrome Windows 10wyf
Google Chrome MacOS设备
Google Chrome Windows 10设备
Google Chrome Windows 10为凤尾
Google Chrome Windows 10denswdfsfdsf
Google Chrome Windows 10111
Google Chrome Windows 10fdf
Google Chrome Windows 10QuXin
Google Chrome Windows 10qing
Google Chrome Windows 10麦冬
Google Chrome Windows 10