理解 Nuxt 和 Vue 钩子和生命周期(第 1 部分)
记住,年轻的徒弟:DRY
回顾:Vue 生命周期
回顾:Nuxt 专用工具
例子
记住,年轻的徒弟:DRY
我们在开发生涯的早期就学到的软件开发原则之一就是 DRY(不要重复自己)。这也是一件好事,因为没有什么比试图在庞大的代码库中爬行,试图找到所有相同逻辑的复制粘贴实例更糟糕的了。
刚开始使用 Vue(后来是 Nuxt)时,我总是不确定某些代码该放在哪里,比如从服务器获取数据,或者检查用户是否登录。于是,我进入了本系列的主题。我将首先快速回顾一下 Vue/Nuxt 架构中可用的机制,然后举例说明每种机制在哪些情况下可能有用,并指出我们出错的地方,以便您避免重复,最后用一个小的参考表来总结整个内容。
最棘手的方面之一是协调服务器端渲染 (SSR) 和客户端之间的差异,在某些情况下,我们必须弄清楚为什么刷新时可以正常工作,但路由更改时却不行,反之亦然。我们有时会弄错各种钩子/方法的调用时机,更重要的是,我们有时会弄错它们没有被调用。这些信息通常可以在文档中找到(而且,文档在过去一年左右已经有了很大的改进),但我认为将它们全部集中在一个地方是很好的。
回顾:Vue 生命周期
Vue 文档中有一张很棒的图表,展示了 Vue 组件方法的调用顺序/情况。可惜的是,它没有清楚地提到一些重要的事情(因为这与 Nuxt 在通用模式下的运行方式有关,而不是纯 Vue)。
- 只有beforeCreate和created会在服务端渲染期间(以及客户端)调用。所有其他方法(最重要的是:mounted,它在示例中经常使用)仅在客户端调用。因此,如果您有需要在服务端渲染期间执行的逻辑,mounted 方法(通常适合放置一些额外的逻辑)并不适合执行。
- beforeCreate无法访问组件的 props/data,因为this(组件引用)仍然未定义。
- created确实可以访问this,包括数据和 props,但无法访问 DOM。这有什么关系呢?例如,如果你想使用this.$refs,它们此时尚未初始化。它们只会在 mount 中被处理(可见)。mounted 不会在服务端渲染 (SSR) 中运行。
回顾:Nuxt 专用工具
注意:以下许多方法都接受Nuxt 上下文作为参数之一。
插件
插件是一些代码片段,在 Vue.js 应用实例创建之前,每个访问者都会执行一到两次。你可以让插件在服务器端和客户端都执行(因此总共执行两次),或者只在客户端执行。Nuxt 有一个实用的约定:任何名为 XXX.client.js 的插件都只在客户端执行,而 YYY.server.js 只在服务端渲染 (SSR) 中执行。此外,Nuxt 提供了一个注入方法,允许你将共享的代码/功能在 Vue 实例/组件、Nuxt 上下文和/或 VueX 存储中调用。一个流行的插件是 Axios,它允许你访问共享的 Axios 实例,例如通过 this.$axios。同样,你可以创建自己的插件并访问它,例如通过 this.$eventBus。
模块
模块代码在 Nuxt 启动时执行(即在 Node.js 服务器的生命周期内执行一次)。模块扩展了 Nuxt的功能,例如,它们可以自动添加和配置插件。它不会在浏览器/每个页面上执行,甚至不会在每个访问页面的客户端的服务器上执行。因此,模块并不适合存放需要为每个访问者执行的代码。当然,除非你的 Nuxt 模块将代码添加到每个访问者都会执行的钩子中——但模块代码本身只会运行一次,用于初始化某些钩子。
store/index.js 中的 nuxtServerInit
nuxtServerInit是 SSR 中执行的首批操作之一(仅限 SSR)。它只会对每个访问你网站的访客执行一次(当他们首次导航到你的网站时,或者当他们点击刷新时)。这里非常适合放置 Axios 调用,以获取一些常用数据并将其存储起来。
中间件
中间件在每个页面渲染之前(路由加载之前)执行,无论您是在服务器端还是客户端。您可以使用全局中间件(在 nuxt.config.js 中配置),也可以使用本地中间件,仅附加到某些布局和/或页面。需要注意的是,中间件在渲染之前只执行一次 - 即,在第一次访问页面时,它只会在服务端渲染 (SSR) 中执行。在后续页面/路由中,它只会在客户端执行。同一页面的客户端和服务器端不会同时调用它。
Mixins
Mixins是组件、页面或布局的扩展。它们可以访问被混合到的整个组件,因此可以使用 this.$route、this.$store 以及组件中可以调用的任何其他方法。它们对于提取由于某些原因无法提取为独立组件的常用功能(包括像 mount 这样的钩子)非常有用。简单来说,它们的行为方式就像您将 Mixin 代码复制粘贴到使用它的每个组件中一样。
异步数据和获取
asyncData和fetch方法均在组件初始化之前执行,因此无法访问this。两者都可用于从 API 获取数据以填充组件。两者*均仅在页面(而非组件)中执行。两者都以 Nuxt 上下文作为参数。两者均在首次加载时在服务器端执行,并在后续路由更改时在客户端执行。(注意:关于何时调用或不调用这些方法,这里有一些细微的注意事项,我将在另一篇文章中详细介绍)
- asyncData应该返回一个承诺,或者使用 async/await - 但无论哪种情况,返回的结果都将集成到组件的数据部分
- 另一方面,fetch应该用于 VueX 存储的数据——它不需要返回任何内容,而应该提交存储任何所需的数据。它可以使用 async/await。
奖励:观看路线
在某些特定情况下,当路由参数发生变化时,asyncData 和 fetch 都不会触发。在这种情况下,您可能需要监视路由以刷新数据,或者更改路由器配置。更多详细信息请参阅另一篇文章。
Nuxt 官方文档中有一张图表,展示了各个函数的调用顺序。让我们更详细地了解一下它在典型的用户-应用交互中的含义。
例子
这篇文章的代码(以及本系列中所有更详细的后续内容)可以在Github上找到。
在本系列的下一篇(或几篇)文章中,我将介绍用户浏览应用程序时究竟发生的情况,并指出与上面介绍的工具相关的各种技术和陷阱。
文章来源:https://dev.to/lilianaziolek/understanding-nuxt-vue-hooks-and-lifecycle-part-1-48lc