探讨

nuxt3采用了Hydration水合这样一个概念,用于处理服务端生成静态html与客户端js脚本的结合,实现一个可动态交互的页面应用,这个过程被称之为水合。

水合的过程可能会相对复杂一些,需要考虑到脚本加载、DOM的匹配、交互的激活(事件)、状态管理等等。

其中状态的管理,我目前使用的时候,发现它并不是理想中的那种状态。

理想中可能是:

服务端渲染时发起了一个api请求,获得了用户的数据,此时我们会将其存储到状态管理中,比如pinia之类的,然后客户端获取到服务端返回的数据,然后自己将pinia的数据恢复到内存中,如果使用了持久化存储,应该会自己将其存储到local之中。

但是,实际情况是,如果你想持久化,那你就必须自己在客户端的时候手动存储,也就是说,在服务端拿到的数据,哪怕你确实在代码中写了持久化处理,也是无效的,目前最佳实践就是在onMounted中处理pinia的数据存储。

如果想在服务端拿到状态,我们还是需要使用到cookie。

除了状态管理,最复杂的其实是请求的处理,nuxt提供了好几种请求的方法。

  1. useAsyncData 用于在水合时包装请求体,通过参数key唯一标识,减少服务端与客户端重复请求;
  2. $fetch 用于实际发起请求的方法,类似与axios,基于ofetch库的封装;
  3. useFetch 是将useAsyncData和$fetch封装后的方法,减少每次都手动输入key做唯一标识的麻烦步骤,效果等同于useAsyncData和$fetch的组合;
  4. useLazyAsyncData 用于在水合时不阻断页面的加载展示,比如你有一个b页面,在b页面的setup中就发起了useFetch请求,如果请求需要10s,那么用户就需要等到10s数据获取后,b页面才会进入并展示,如果使用useLazyAsyncData配合$fetch,就会直接进入页面,等数据获取后再渲染对应的dom元素;
  5. 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去请求,是真的会触发两次,一次在服务器,一次在客户端。

此处内容已隐藏回复后方可阅读。

分类: nuxt 标签: cookieNuxt3请求水合useFetch$fetch

评论

全部评论 112

  1. 珈百璃
    珈百璃
    Google Chrome Windows 10
    感谢站长的分享!
  2. sjss
    sjss
    Google Chrome Windows 10
    看看,评论内容请不得少于5个字符
  3. savkk
    savkk
    Google Chrome Windows 10
    看看,评论内容请不得少于5个字符
  4. ...
    ...
    Google Chrome MacOS
    看看,评论内容请不得少于5个字符
  5. eeee
    eeee
    Google Chrome MacOS
    good[微笑]
  6. dfas
    dfas
    Google Chrome MacOS
    困扰了我三天了,看看
  7. 半壶水
    半壶水
    Google Chrome MacOS
    [大哭]困扰了我三天了,看看
    1. 木灵鱼儿
      木灵鱼儿
      FireFox Windows 10
      @半壶水还是得多啃文档啊[辣眼睛]

目录