探讨

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

评论

全部评论 90

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

目录