前言
學習vuex之前,我提出了3個疑問。Vuex 官網(wǎng)
vuex是什么?
官方文檔解釋:vuex是一個專為 Vue.js 應用程序開發(fā)的狀態(tài)管理模式。
通俗點講就是把這個項目中需要多個地方或全局使用的狀態(tài)集中管理起來。vuex應用場景是什么?
舉個栗子
①多個組件依賴一種狀態(tài)。就是說這個狀態(tài)一改變,其他依賴這個狀態(tài)的組件都要跟著改變。如果是兄弟組件,使用傳值的方式的話就比較麻煩。
②多個組件共用同一個請求的數(shù)據(jù)。我比較懶,又不想在多個組件寫相同的請求,而且增加重復代碼,怎么辦?這時候vuex就派上用場了。
從以上兩個栗子得出:需要集中管理共同狀態(tài)的都可以使用vuex(不要濫用)vuex怎么用?
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.store({
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... },
modules: { ... }
})
// index.js
import Vue from 'vue';
import store from '/store';
new Vue({
// 全局掛載 Vuex
store
})
在真正使用之前,你要了解 vuex 擴展的幾個核心概念。
Vuex 核心概念
第一次看官方文檔的時候,對下面幾個概念不是很理解,認真看文檔,換個理解方式就好多了。
-
state:管理狀態(tài)的地方;可以類比成vue里面的data。
注意:state(狀態(tài)) 不能像 data 的屬性那樣通過賦值改變,只能通過 mutations 改變,這樣的目的是為了更好地追蹤狀態(tài)的變化
export default new Vuex.Store({
state: {
count: 1,
...
}
})
-
mutations:改變state(狀態(tài))的地方;可以類比成vue里面的methods。
mutations里面所有回調函數(shù)接受的第一個參數(shù)是state,其余參數(shù)是commit傳的。
注意:mutations 是同步觸發(fā)的,無法監(jiān)聽回調函數(shù)中進行的狀態(tài)的改變;那我要寫異步請求改變狀態(tài)怎么辦,actions 才是干這事的。
export default new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 改變狀態(tài);也就是修改 state 里面 count 的值
state.count++
}
}
})
那怎么調用mutations的方法改變state?通過commit(提交)的方式。
// ...
mutations: {
increment (state, n) {
state.count += n
},
increment1 (state, params) {
state.count += params.amount
}
}
// ***.vue
// 普通方式提交
this.$store.commit('increment', 10)
// 以對象形式提交
this.$store.commit({
type: 'increment1',
amount: 10
})
-
actions:類似于mutation,但不同的是①actions提交的是mutation,而不是直接改變state; ②actions可以包含任意異步操作。
actions接受的第一個參數(shù)是Store實例具有相同方法和屬性的context對象,其余參數(shù)是dispatch分發(fā)的
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
incrementAsync(context) {
context.commit('increment')
},
// 參數(shù)解構
incrementAsync1 ({ commit, getters }, params) {
commit('increment')
},
// 回調方式提交
incrementAsync2 ({ commit, getters }, params) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
})
那怎么調用actions的方法? 通過dispatch(分發(fā))的方式。
// 以普通方式分發(fā)
this.$store.dispatch('incrementAsync')
// 以載荷形式分發(fā)
this.$store.dispatch('incrementAsync1', {
amount: 10
})
// 以對象形式分發(fā)
this.$store.dispatch({
type: 'incrementAsync2',
amount: 10
})
-
getters:可以看做是Store實例的計算屬性;用法與vue的計算屬性一致。
getters的返回值會根據(jù)它的依賴被緩存起來,且只有當它的依賴值發(fā)生了改變才會被重新計算。
getters只接受兩個參數(shù)state、getters。要是實現(xiàn)給getter傳參,只能通過讓getter返回一個函數(shù)。
export default new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
// 接收兩個參數(shù)
doneTodos1: (state, getters) => {
return getters.doneTodos.length
},
// 返回一個函數(shù)
doneTodos2: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
})
調用 getters
注意:getter 在通過方法訪問時,每次都會去進行調用,而不會緩存結果。
// 通過屬性調用
this.$store.getters.doneTodos1
// 通過方法調用
this.$store.getters.doneTodos2(1)
-
modules:模塊的意思;每個模塊擁有自己的state、mutation、actions、getters、甚至是嵌套子模塊。
當項目非常復雜時候,將Store分割成多個module(模塊)管理的話維護起來就方便多了。
// ...
export default new Vuex.Store({
modules: {
moduleA,
moduleB
}
})
總結
- 如果認真看完就會發(fā)現(xiàn)與官網(wǎng)給的核心概念的目錄順序不同,我建議看文檔的順序是先看
state、mutation、actions,然后再看getters、modules,這樣相對容易理解。 - 詳情請移步 Vuex 官網(wǎng)