您正在浏览 Nuxt 2 文档。前往 Nuxt 3 文档, 或了解更多关于 Nuxt 2 长期支持

Store 目录

store 目录包含 Vuex store 相关文件。Vuex Store 随 Nuxt 一起提供,开箱即用,但默认禁用。在此目录中创建 index.js 文件即可启用 store。


此目录不能在没有额外配置的情况下重命名。

使用 store 管理状态对于任何大型应用程序都很重要,这就是 Nuxt 将 Vuex 集成到其核心的原因。

启用 Store

Nuxt 会检查 store 目录,如果包含非隐藏文件或 README.md 以外的文件,store 就会被启用,这意味着 Nuxt 会:

  1. 导入 Vuex
  2. store 选项添加到根 Vue 实例

模块

store 目录中的所有 .js 文件都会转换为命名空间模块 index 成为根模块)。state 的值应始终是 function,以避免在服务端共享不必要的状态。

首先,将 state 导出为函数,将 mutations 和 actions 导出为对象:

store/index.js
export const state = () => ({
  counter: 0
})

export const mutations = {
  increment(state) {
    state.counter++
  }
}

然后创建 store/todos.js 文件:

store/todos.js
export const state = () => ({
  list: []
})

export const mutations = {
  add(state, text) {
    state.list.push({
      text,
      done: false
    })
  },
  remove(state, { todo }) {
    state.list.splice(state.list.indexOf(todo), 1)
  },
  toggle(state, todo) {
    todo.done = !todo.done
  }
}

store 会生成如下:

new Vuex.Store({
  state: () => ({
    counter: 0
  }),
  mutations: {
    increment(state) {
      state.counter++
    }
  },
  modules: {
    todos: {
      namespaced: true,
      state: () => ({
        list: []
      }),
      mutations: {
        add(state, { text }) {
          state.list.push({
            text,
            done: false
          })
        },
        remove(state, { todo }) {
          state.list.splice(state.list.indexOf(todo), 1)
        },
        toggle(state, { todo }) {
          todo.done = !todo.done
        }
      }
    }
  }
})

pages/todos.vue 中可以这样使用 todos 模块:

pages/todos.vue
<template>
  <ul>
    <li v-for="todo in todos" :key="todo.text">
      <input :checked="todo.done" @change="toggle(todo)" type="checkbox">
      <span :class="{ done: todo.done }">{{ todo.text }}</span>
    </li>
    <li><input @keyup.enter="addTodo" placeholder="What needs to be done?"></li>
  </ul>
</template>

<script>
import { mapMutations } from 'vuex'

export default {
  computed: {
    todos () {
      return this.$store.state.todos.list
    }
  },
  methods: {
    addTodo (e) {
      this.$store.commit('todos/add', e.target.value)
      e.target.value = ''
    },
    ...mapMutations({
      toggle: 'todos/toggle'
    })
  }
}
</script>

<style>
.done {
  text-decoration: line-through;
}
</style>

模块方法也可以在顶层定义,无需在 store 目录中添加子目录。

state 示例:创建 store/state.js 如下:

export default () => ({
  counter: 0
})

对应的 mutations 可以放在 store/mutations.js 中:

store/mutations.js
export default {
  increment(state) {
    state.counter++
  }
}

示例文件夹结构

复杂 store 配置的文件/文件夹结构如下:

 store/
--| index.js
--| ui.js
--| shop/
----| cart/
------| actions.js
------| getters.js
------| mutations.js
------| state.js
----| products/
------| mutations.js
------| state.js
------| itemsGroup1/
--------| state.js

Store 中的插件

通过在 store/index.js 文件中添加,可以向 store 添加插件:

store/index.js
import myPlugin from 'myPlugin'

export const plugins = [myPlugin]

export const state = () => ({
  counter: 0
})

export const mutations = {
  increment(state) {
    state.counter++
  }
}

有关插件的更多信息:Vuex 文档

nuxtServerInit 操作

如果 store 中定义了 nuxtServerInit 操作且模式为 universal,Nuxt 会在服务端调用它并传入上下文(仅服务端)。这在将服务器上的某些数据直接传递到客户端时很有用。

例如,服务端有 session,可以通过 req.session.user 访问已连接的用户。要将认证用户传递给 store,请修改 store/index.js 如下:

store/index.js
actions: {
  nuxtServerInit ({ commit }, { req }) {
    if (req.session.user) {
      commit('user', req.session.user)
    }
  }
}
此操作只有主模块(store/index.js 中)才能接收,需要从这里链接调用其他模块的操作。

上下文 作为 nuxtServerInit 的第二个参数传入,与 asyncData 方法类似。

运行 nuxt generate 时,nuxtServerInit 会在所有动态生成的路由上执行。

异步的 nuxtServerInit 操作必须返回 Promise 或使用 async/await,以便 nuxt 服务器等待它。
store/index.js
actions: {
  async nuxtServerInit({ dispatch }) {
    await dispatch('core/load')
  }
}

Vuex 严格模式

严格模式在开发模式下默认启用,在生产模式下禁用。要在开发模式下也禁用严格模式,请按照以下示例修改 store/index.js

export const strict = false
Edit this page on GitHub Updated at Tue, Apr 14, 2026