對(duì)于每個(gè)大項(xiàng)目來(lái)說(shuō),使用狀態(tài)樹(shù) (store) 管理狀態(tài) (state) 十分有必要。這就是為什么 Nuxt.js 內(nèi)核實(shí)現(xiàn)了 Vuex。
Nuxt.js 會(huì)嘗試找到應(yīng)用根目錄下的 store 目錄,如果該目錄存在,它將做以下的事情:
Nuxt.js 支持兩種使用 store 的方式,你可以擇一使用:
無(wú)論使用那種模式,您的state的值應(yīng)該始終是function,為了避免返回引用類(lèi)型,會(huì)導(dǎo)致多個(gè)實(shí)例相互影響。
Nuxt.js允許您擁有一個(gè) store 目錄,其中包含與模塊對(duì)應(yīng)的每個(gè)文件。
首先,只需將狀態(tài)導(dǎo)出為 函數(shù),將變量和操作作為 store/index.js 中的對(duì)象導(dǎo)出:
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將如下創(chuàng)建:
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="checkbox" :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>
模塊方法也適用于頂級(jí)定義,而無(wú)需在 store 目錄中實(shí)現(xiàn)子目錄
示例:您創(chuàng)建文件 store/state.js 并添加以下內(nèi)容
export default () => ({
counter: 0
})
相應(yīng)的可以在文件夾中添加 store/mutations.js
export default {
increment (state) {
state.counter++
}
}
您可以將模塊文件分解為單獨(dú)的文件:state.js,actions.js,mutations.js和getters.js。如果您使用index.js來(lái)維護(hù)state,getters,actions和mutations,同時(shí)具有單個(gè)單獨(dú)的操作文件,那么仍然可以正確識(shí)別該文件。
注意:在使用拆分文件模塊時(shí),必須記住使用箭頭函數(shù)功能, this 在詞法上可用。詞法范圍this意味著它總是指向引用箭頭函數(shù)的所有者。如果未包含箭頭函數(shù),那么this將是未定義的(undefined)。解決方案是使用 "normal" 功能,該功能會(huì)將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++
}
}
有關(guān)插件的更多信息: Vuex 文檔.
fetch 方法會(huì)在渲染頁(yè)面前被調(diào)用,作用是填充狀態(tài)樹(shù) (store) 數(shù)據(jù),與 asyncData 方法類(lèi)似,不同的是它不會(huì)設(shè)置組件的數(shù)據(jù)。
關(guān)于 fetch 方法的更多信息,請(qǐng)參考 頁(yè)面 fetch 方法API。
如果在狀態(tài)樹(shù)中指定了 nuxtServerInit 方法,Nuxt.js 調(diào)用它的時(shí)候會(huì)將頁(yè)面的上下文對(duì)象作為第2個(gè)參數(shù)傳給它(服務(wù)端調(diào)用時(shí)才會(huì)醬紫喲)。當(dāng)我們想將服務(wù)端的一些數(shù)據(jù)傳到客戶(hù)端時(shí),這個(gè)方法是灰常好用的。
舉個(gè)例子,假設(shè)我們服務(wù)端的會(huì)話(huà)狀態(tài)樹(shù)里可以通過(guò) req.session.user 來(lái)訪(fǎng)問(wèn)當(dāng)前登錄的用戶(hù)。將該登錄用戶(hù)信息傳給客戶(hù)端的狀態(tài)樹(shù),我們只需更新 store/index.js 如下:
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}
如果你使用_狀態(tài)樹(shù)模塊化_的模式,只有主模塊(即 store/index.js)適用設(shè)置該方法(其他模塊設(shè)置了也不會(huì)被調(diào)用)。
這時(shí)context被賦予nuxtServerInit作為第二個(gè)參數(shù),它與asyncData或fetch方法相同。
nuxtServerInit 方法接收的上下文對(duì)象和 fetch 的一樣,但不包括 context.redirect() 和 context.error()。
注意:異步nuxtServerInit操作必須返回Promise來(lái)通知nuxt服務(wù)器等待它們。
actions: {
async nuxtServerInit({ dispatch }) {
await dispatch('core/load')
}
}
默認(rèn)情況下,在開(kāi)發(fā)模式下啟用嚴(yán)格模式,在生產(chǎn)模式下關(guān)閉模式。要在dev中禁用嚴(yán)格模式,請(qǐng)遵循以下示例。
export const strict = false
此功能已經(jīng)棄用,將在Nuxt 3中刪除。
要使用經(jīng)典模式創(chuàng)建Vuex,我們應(yīng)該創(chuàng)建store/index.js到處返回Vuex實(shí)例的方法的文件:
import Vuex from 'vuex'
const createStore = () => {
return new Vuex.Store({
strict: false,
state: () => ({
counter: 0
}),
mutations: {
increment (state) {
state.counter++
}
}
})
}
export default createStore
我們不需要安裝,因?yàn)閂uex由Nuxt.js提供。
我們現(xiàn)在可以在我們的組件中使用this.$store:
<template>
<button @click="$store.commit('increment')">{{ $store.state.counter }}</button>
</template>
更多建議: