Vuex 状态树
对于每个大项目来说,使用状态树 (store) 管理状态 (state) 十分有必要。这就是为什么 Nuxt.js 内核实现了 。
使用状态树
Nuxt.js 会尝试找到src目录(认是应用根目录)下的 store 目录,如果该目录存在,它将做以下的事情:
引用 vuex 模块
将 vuex 模块 加到 vendors 构建配置中去
设置 Vue 根实例的 store 配置项
Nuxt.js 两种使用 store 的方式,你可以择一使用:
模块方式: store 目录下的每个 .js 会被转换成为状态树 (当然,index 是根模块)
Classic(不建议使用): store/index.js返回创建Vuex.Store实例的。
无论使用那种模式,您的state的值应该始终是function,为了避免返回引用类型,会导致多个实例相互影响。
Nuxt.js允许您拥有 store 目录,其中包含与模块对应的每个。
首先,只需将状态导出为 ,将变量和操作作为 store/index.js 中的对象导出:
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 } }
Vuex将如下创建:
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"> <input type="check@R_908_2@" :checked="todo.done" @change="toggle(todo)"> <span :class="{ done: todo.done }">{{ todo.text }}</span> </li> <li><input placeholder="What needs to be done?" @keyup.enter="addTodo"></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 目录中实现子目录
示例:您 store/state.js 并以下
export default () => ({ counter: 0 })
相应的可以在夹中 store/mutations.js
export default { increment (state) { state.counter++ } }
您可以将模块分解为单独的:state.js,actions.js,mutations.js和getters.js。如果您使用index.js来维护state,getters,actions和mutations,同时具有单个单独的操作,那么仍然可以正确识别该。
注意:在使用拆分模块时,必须记住使用箭头, this 在词法上可用。词法范围this意味着它总是指向引用箭头的所有者。如果未包含箭头,那么this将是未定义的(undefined)。案是使用 "normal" ,该会将this指向自己的作用域,因此可以使用。
您可以将其他到store(在模块模式下),将其放入store/index.js中:
import myPlugin from 'myPlugin' export const plugins = [ myPlugin ] export const state = () => ({ counter: 0 }) export const mutations = { increment (state) { state.counter++ } }
有关的更多信息: .
fetch
fetch 会在渲染前被,作用是填充状态树 (store) 数据,与 asyncData 类似,不同的是它不会设置组件的数据。
关于 fetch 的更多信息,请参考 fetch API。
nuxtServerInit
如果在状态树中指定了 nuxtServerInit ,Nuxt.js 它的时候会将的上下文对象作为第2个参数传给它(服务端时才会酱紫哟)。当我们想将服务端的一些数据传到客户端时,这个是灰常好用的。
举个例子,假设我们服务端的会话状态树里可以通过 req.session.user 来访问当前的。将该信息传给客户端的状态树,我们只需更新 store/index.js 如下:
actions: { nuxtServerInit ({ commit }, { req }) { if (req.session.user) { commit('user', req.session.user) } } }
如果你使用_状态树模块化_的模式,只有主模块(即 store/index.js)适用设置该(其他模块设置了也不会被)。
这时context被赋予nuxtServerInit作为第二个参数,它与asyncData或fetch相同。
nuxtServerInit 接收的上下文对象和 fetch 的一样,但不 context.redirect() 和 context.error()。
注意:异步nuxtServerInit操作必须返回Promise来nuxt服务器等待它们。
actions: { async nuxtServerInit({ dispatch }) { await dispatch('core/load') } }
Vuex 严格模式
认情况下,在开发模式下启用严格模式,在生产模式下模式。要在dev中禁用严格模式,请遵循以下示例。
export const strict = false
此已经弃用,将在Nuxt 3中。
要使用经典模式创建Vuex,我们应该创建store/index.js到处返回Vuex实例的的:
import Vuex from 'vuex' const createStore = () => { return new Vuex.Store({ strict: false, state: () => ({ counter: 0 }), mutations: { increment (state) { state.counter++ } } }) } export default createStore
我们不需要安装,因为Vuex由Nuxt.js提供。
我们现在可以在我们的组件中使用this.$store:
<template> <button @click="$store.commit('increment')">{{ $store.state.counter }}</button> </template>