Skip to content

6. 示例 [nuxt-03]:nuxtServerInit

[nuxt-03] 项目旨在展示 [Vuex] 存储中名为 [nuxtServerInit] 的函数。 该函数允许服务器像 [fetch] 函数那样初始化存储 [Vuex]。 但与函数 [fetch] 不同,函数 [nuxtServerInit] 绝不会由客户端执行。

Image

项目 [nuxt-03] 最初是通过复制项目 [nuxt-01] 获得的,随后从该项目中删除了文件夹 [pages] 中的页面 [page2] 以及组件 [navigation]组件中移除了页面[page2]。文件夹[store]是通过复制文件夹[nuxt-02/store]获得的。

6.1. [Vuex]存储

[Vuex] 存储将通过以下 [store/index.js] 文件实现:


/* eslint-disable no-console */
export const state = () => ({
  // 计数器
  counter: 0
})

export const mutations = {
  // 将计数器增加一个值[inc]
  increment(state, inc) {
    state.counter += inc
  }
}

export const actions = {
  async nuxtServerInit(store, context) {
    // 谁在执行这段代码?
    console.log('nuxtServerInit, client=', process.client, 'serveur=', process.server)
    // 正在等待一个 Promise 完成
    await new Promise(function(resolve, reject) {
      // 这里通常有一个异步函数
      // 通过等待一秒来模拟该函数
      setTimeout(() => {
        // 成功
        resolve()
      }, 1000)
    })
    // 修改存储器
    store.commit('increment', 34)
    // 日志
    console.log('nuxtServerInit commit terminé')
  }
}
  • 第 1-12 行:与项目 [nuxt-02] 中的内容相同;
  • 第 14-32 行:导出一个 [actions] 对象。这是 [Vuex] 存储库中的一个保留术语;
  • 第 15 行:定义函数 [nuxtServerInit]。该函数将在服务器启动应用程序时被执行。 其通常的作用是利用通过异步函数获取的外部数据来初始化存储 [Vuex]。[nuxt] 会等待该函数返回结果,然后才开始处理所请求页面的生命周期。该函数接收两个参数:
    • 待初始化的存储 [Vuex];
    • 当前的上下文 [nuxt];
  • 第 19-26 行:等待异步操作结束,此处人为设置了一秒的等待时间(第 15 行);
  • 第 28 行:将计数器值设为 34;
  • 第 17 和 30 行:用于跟踪函数 [nuxtServerInit] 执行过程的日志;

6.2. 页面 [index]

页面 [index] 将如下所示:


<!-- 页面 [index] -->
<template>
  <Layout :left="true" :right="true">
    <!-- 导航 -->
    <Navigation slot="left" />
    <!-- 消息-->
    <b-alert slot="right" show variant="warning"> Home - value= {{ value }} </b-alert>
  </Layout>
</template>

<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */

import Layout from '@/components/layout'
import Navigation from '@/components/navigation'
export default {
  name: 'Home',
  // 使用的组件
  components: {
    Layout,
    Navigation
  },
  data() {
    return {
      value: 0
    }
  },
  // 生命周期
  beforeCreate() {
    // 客户端与服务器
    console.log('[home beforeCreate]')
  },
  created() {
    // 客户端与服务器
    this.value = this.$store.state.counter
    console.log('[home created], value=', this.value)
  },
  beforeMount() {
    // 仅客户端
    console.log('[home beforeMount]')
  },
  mounted() {
    // 仅客户端
    console.log('[home mounted]')
  }
}
</script>
  • 第 37 行:由函数 [nuxtServerInit] 初始化的计数器值被赋给第 27 行的属性 [value]。该值由第 7 行显示;
  • 第 37 行将由服务器和客户端同时执行。在两种情况下,属性 [value] 都将获得相同的值,从而确保服务器生成的页面与客户端生成的页面完全一致;

6.3. 页面 [page1]

页面 [page1] 是通过复制页面 [index] 获得的。随后修改其文本,将 [home] 替换为 [page1]:


<!-- 页面 [page1]] -->
<template>
  <Layout :left="true" :right="true">
    <!-- 导航 -->
    <Navigation slot="left" />
    <!-- 消息-->
    <b-alert slot="right" show variant="warning"> Page1 - value= {{ value }} </b-alert>
  </Layout>
</template>

<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */

import Layout from '@/components/layout'
import Navigation from '@/components/navigation'

export default {
  name: 'Page1',
  // 使用的组件
  components: {
    Layout,
    Navigation
  },
  data() {
    return {
      value: 0
    }
  },
  // 生命周期
  beforeCreate() {
    // 客户端与服务器
    console.log('[page1 beforeCreate]')
  },
  created() {
    // 客户端与服务器
    this.value = this.$store.state.counter
    console.log('[page1 created], value=', this.value)
  },
  beforeMount() {
    // 仅客户端
    console.log('[page1 beforeMount]')
  },
  mounted() {
    // 仅客户端
    console.log('[page1 mounted]')
  }
}
</script>

此页面仅用于实现两页之间的导航。

6.4. Exécution

文件 [nuxt.config.js] 修改如下:


// 源代码目录
  srcDir: 'nuxt-03',
  // 路由器
  router: {
    // 应用程序的 URL 根目录
    base: '/nuxt-03/'
  },
  // 服务器
  server: {
    // 服务端口,默认 3000
    port: 81,
    // 监听的网络地址,默认 localhost:127.0.0.1
    // 0.0.0.0 = 该机器的所有网络地址
    host: 'localhost'
}

执行时显示的页面如下:

Image

  • 在 [5] 中,可以看到服务器在页面 [index] 的生命周期开始之前就已执行了函数 [nuxtServerInit]。 [nuxt] 等待异步函数完成工作后才进入生命周期;
  • 在 [4] 中,可以看到客户端并未执行 [nuxtServerInit] 函数;

现在进行两次导航:index --> page1 --> index。此时日志如下:

Image

  • 在 [1-2] 中,可以看到客户端未执行函数 [nuxtServerInit];

现在手动输入页面 [page1] 中的 URL,以强制调用服务器:

Image

在 [3-4] 中,我们发现与启动时加载 [index] 页面之前相同的机制。 在此重申先前所述:当强制向服务器调用页面时,其效果等同于应用程序重新启动,并将所请求的页面作为首页;