Skip to content

7. 示例 [nuxt-04]:客户端/服务器会话的维持

项目 [nuxt-04] 探讨了客户端/服务器会话维护的问题。我们基于项目 [nuxt-03] 进行如下修改:

  • 页面 [index] 将包含一个按钮,用于递增存储 [Vuex] 中的计数器;
  • 页面 [page1] 保持不变;
  • 希望当手动向服务器请求页面时,服务器返回所请求的页面,并附带一个名为 [Vuex] 的存储,其计数器值应为该存储在客户端的最后一个值;

项目 [nuxt-04] 最初是通过复制项目 [nuxt-03] 创建的:

Image

仅 [index] 页面发生变更:


<!-- 页面 [index] -->
<template>
  <Layout :left="true" :right="true">
    <!-- 导航 -->
    <Navigation slot="left" />
    <!-- 消息-->
    <template slot="right">
      <b-alert show variant="warning"> Home - value= {{ value }} </b-alert>
      <!-- 按钮 -->
      <b-button @click="incrementCounter" class="ml-3" variant="primary">Incrémenter</b-button>
    </template>
  </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]')
  },
  // 事件管理
  methods: {
    incrementCounter() {
      console.log('incrementCounter')
      // 计数器递增 1
      this.$store.commit('increment', 1)
      // 更改显示值
      this.value = this.$store.state.counter
    }
  }
}
</script>
  • 第 10 行:添加了一个按钮,用于递增 [Vuex] 存储器的计数器;
  • 第 54 行:处理 [clic] 的方法已添加到按钮 [Incrémenter] 上;
  • 第 57 行:百叶窗计数器加 1;
  • 第 59 行:将计数器的值赋给属性 [value],以便在第 8 行中显示该值;

执行项目 [nuxt-04],使用以下文件 [nuxt.config.js]:


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

运行时显示的首页如下:

Image

多次点击按钮 [3] 后,显示如下新页面:

Image

若点击链接 [3],将显示以下页面:

Image

  • 在 [2] 中,页面 [page1] [1] 正确显示了计数器的数值;

现在,我们使用 [3] 刷新页面。新页面如下:

Image

  • 在 [2] 中,当前计数器的值丢失了。它回到了初始值;

如果查看日志,这个结果完全可以理解:

  • 在 [1] 中,服务器重新执行了 [nuxtServerInit] 函数。而该函数如下:
/* 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', 53)
     // 日志
    console.log('nuxtServerInit commit terminé')
  }
}

第 28 行将计数器赋值为 53。

让我们来分析一下,当刷新页面 [page1] 时,浏览器发出的请求 HTTP:

Image

可以看到,除了页面 [page1] 和 [1] 之外,客户端还向服务器请求了若干脚本。 值得注意的是 [pages_index, pages_page1] 脚本,它们是与页面 [index, page] 相关的脚本。无论请求的是哪个页面,每次向服务器发送请求时都会提供这些脚本;

在 [1] 中,通过以下请求 HTTP 向服务器请求页面 [page1]:

GET http://localhost:81/nuxt-04/page1
Host: localhost:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache

可以看出,该请求并未向服务器传输任何信息。因此,服务器无法获知客户端 [Vuex] 的状态。要实现这一点,客户端本应向服务器发送该信息。

在接下来的项目 [nuxt-05] 中,我们使用 Cookie 使客户端能在服务器被调用时向其发送信息。