Nuxt.js特有的两个生命周期:asyncData、fetch

2023-04-16 0 312

您好,我是bp技术知识库,欢迎关注。


最近帮同事找Nuxt项目问题时,发现Nuxt提供了2个生命周期,分别是:

  • asyncData
  • fetch

中文文档中对于这2个生命周期的介绍非常短,看完后我一头雾水,经过我的反复研究以及各种试验后,大致明白了这2个生命周期的用途和用法。

1. asyncData

asyncData方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用 asyncData方法来获取数据,Nuxt.js 会将 asyncData 返回的数据融合组件 data 方法返回的数据一并返回给当前组件。

简单的说,就是asyncData只能用于页面组件,不能用于自定义组件,它可以返回一个对象,该对象中的值会覆盖data中对应的属性值。

并且asyncData中没有this来引用组件实例,但是它有一个context参数,大致用法如下:

<template>
  <div>{{ content }}</div>
</template>

<script lang="ts">
import Vue from "vue";

export default Vue.extend({
  name: "IndexPage",
  async asyncData({$axios}) {
    const res = await $axios.$get("http://localhost:5000");
    return {content: res.content};
  },
  data() {
    return {
      content: "",
    };
  },
});
</script>

查看网页源代码:

Nuxt.js特有的两个生命周期:asyncData、fetch

2. fetch

fetch 方法用于在渲染页面前填充应用的状态树(store)数据, 与 asyncData 方法类似,不同的是它不会设置组件的数据。

可以在任何组件中使用,无论是页面组件还是自定义组件。

需要注意的是,中文文档上面的内容已经过时了,由于过时的问题,带有非常强烈的误导性:

Nuxt.js特有的两个生命周期:asyncData、fetch

现在在fetch中是可以使用this获取到组件实例,并且也可以通过this去更改data中的属性。在英文文档中,官方对于fetch的介绍非常的完善,不像中文文档中是一段文字就给带过去了。

根据英文文档中,在Nuxt的2.12版本及之后,fetch的用法跟之前的版本完全不一样,而如果你在fetch中接受了一个context对象,那么它将被视为旧版的fetch,现在官方已经不推荐这么使用了。

我之前没有好好读英文文档,所以在试验的时候发现了一个坑点,直接看下面的代码吧:

async fetch() {
  const res = await fetch('http://localhost:5000').then(res=>res.json());
  // 这里赋值后界面正确渲染
  this.content = res.content;
},

我改变请求方式后:

async fetch({ $axios }) {
  const res = await $axios.$get('http://localhost:5000');
  // 这里赋值后发现界面上并没有渲染出对应的值
  this.content = res.content;
},

我把请求方式换成了Nuxt自带的axios,我发现页面上的内容没有正确的渲染出来,当时我完全没有找到原因所在。

而根据英文文档,在fetch中不能使用context,如果你使用了context参数,那么就会被视为旧版fetch。

如果你要使用context,那么推荐你使用asyncData或者匿名中间件,所以上面的请求应该这么写:

async fetch() {
  // 从this中获取$axios而不是从context中获取
  const res = await this.$axios.$get("http://localhost:5000");
  // 这里界面上就能正确的渲染出数据
  this.content = res.content;
},

查看网页源代码:

Nuxt.js特有的两个生命周期:asyncData、fetch

3. 传统请求

知道asyncData和fetch大致用法后,我们就得来看看为什么要用这两个生命周期进行请求,为什么不在created、mounted这种Vue中常用的生命周期中进行网络请求。

还是上面的请求:

async mounted() {
  const res = await this.$axios.$get("http://localhost:5000");
  this.content = res.content;
},

查看网页源代码:

Nuxt.js特有的两个生命周期:asyncData、fetch

可能你已经发现了区别,在mounted中进行请求,查看网页源代码的时候是看不到对应的数据,如果在网页源代码无法看到对应的数据,那么搜索引擎极大可能抓取不到这些数据。

如果你想要减小服务端的压力,比如一些对于SEO没有什么帮助的请求数据,那么你完全可以放在mounted中进行请求,因为mounted生命周期是在客户端进行运行的。

至于created这个生命周期,我实测的时候它会在服务端运行一次,然后又在客户端运行一次。

Nuxt.js特有的两个生命周期:asyncData、fetch

这可能关系到Nuxt生命周期的问题,我暂时就没有深入研究,所以没有发言权,而且官方也说的是如果你想要使用传统的Vue请求方式,那么将请求放在mounted生命周期中。

4. 用户信息

使用这2个生命周期,可以让你的项目获得更好的SEO,但是值得注意的是,这2个生命周期都是在服务端中运行,而服务端是没有window对象的,也就无法使用localstorage,如果要进行用户身份的验证,那么推荐是使用cookie来存储用户的身份信息。

使用js-cookie可以很方便的操作cookie。

5. 好处

现在很多搜索引擎的爬虫已经能够解析JavaScript文件,从而获取JavaScript文件上面重要的内容。

但是异步请求的数据是没有办法获取的,所以使用asyncData和fetch将一些重要的数据放在服务端进行请求,然后服务端返给客户端的HTML上就已经获取到了这些数据,这样有2个好处:

  • 较短的白屏时间。
  • 更好的SEO。

当很多数据是通过异步进行请求的时候,打开页面经常会出现页面坍缩,获取到数据渲染完成后页面才会正常显示,虽然可能就那么一瞬间,但是对于用户来说也会造成不好的体验。

而使用服务端渲染就不会有这些问题,因为数据已经在服务端获取完毕了,也就不会出现页面短暂坍塌的情况。

6. 最后

服务端渲染带来更好的SEO的同时,对于服务器的负担也是指数倍的,比如单页面应用布置到Nginx上面可能就占几M的内存,而如果是服务端渲染的情况下可能达到几百M甚至更多,要知道,服务器的内存可是非常贵的,内存每翻一倍,价格都要翻好几倍。

至于要不要做服务端渲染,还是得根据自身的情况来定,不过遇到官网这种外包项目,如果用的Vue技术栈那么选Nuxt肯定是没错的。

客户不做SEO,你可以打包成单页面应用,如果需要SEO,那你也可以毫无压力的开启服务端渲染,多做一手准备少加班。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务