Store 目录
store 目录包含 Vuex store 相关文件。Vuex Store 随 Nuxt 一起提供,开箱即用,但默认禁用。在此目录中创建 index.js 文件即可启用 store。
使用 store 管理状态对于任何大型应用程序都很重要,这就是 Nuxt 将 Vuex 集成到其核心的原因。
启用 Store
Nuxt 会检查 store 目录,如果包含非隐藏文件或 README.md 以外的文件,store 就会被启用,这意味着 Nuxt 会:
- 导入 Vuex
-
将
store选项添加到根 Vue 实例
模块
store 目录中的所有 .js 文件都会转换为命名空间模块 (index 成为根模块)。state 的值应始终是 function,以避免在服务端共享不必要的状态。
首先,将 state 导出为函数,将 mutations 和 actions 导出为对象:
export const state = () => ({
counter: 0
})
export const mutations = {
increment(state) {
state.counter++
}
}
然后创建 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 模块:
<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 中:
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 添加插件:
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 如下:
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 服务器等待它。actions: {
async nuxtServerInit({ dispatch }) {
await dispatch('core/load')
}
}
Vuex 严格模式
严格模式在开发模式下默认启用,在生产模式下禁用。要在开发模式下也禁用严格模式,请按照以下示例修改 store/index.js:
export const strict = false