前言
學習vuex
之前,我提出了3個疑問。Vuex 官網
vuex
是什么?
官方文檔解釋:vuex
是一個專為 Vue.js 應用程序開發的狀態管理模式
。
通俗點講就是把這個項目中需要多個地方或全局使用的狀態集中管理起來。vuex
應用場景是什么?
舉個栗子
①多個組件依賴一種狀態。就是說這個狀態一改變,其他依賴這個狀態的組件都要跟著改變。如果是兄弟組件,使用傳值的方式的話就比較麻煩。
②多個組件共用同一個請求的數據。我比較懶,又不想在多個組件寫相同的請求,而且增加重復代碼,怎么辦?這時候vuex
就派上用場了。
從以上兩個栗子得出:需要集中管理共同狀態的都可以使用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
:管理狀態的地方;可以類比成vue
里面的data
。
注意:state(狀態) 不能像 data 的屬性那樣通過賦值改變,只能通過 mutations 改變,這樣的目的是為了更好地追蹤狀態的變化
export default new Vuex.Store({
state: {
count: 1,
...
}
})
-
mutations
:改變state
(狀態)的地方;可以類比成vue
里面的methods
。
mutations
里面所有回調函數
接受的第一個參數是state
,其余參數是commit
傳的。
注意:mutations 是同步觸發的,無法監聽回調函數中進行的狀態的改變;那我要寫異步請求改變狀態怎么辦,actions 才是干這事的。
export default new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 改變狀態;也就是修改 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
接受的第一個參數是Store
實例具有相同方法和屬性的context
對象,其余參數是dispatch
分發的
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
incrementAsync(context) {
context.commit('increment')
},
// 參數解構
incrementAsync1 ({ commit, getters }, params) {
commit('increment')
},
// 回調方式提交
incrementAsync2 ({ commit, getters }, params) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
})
那怎么調用actions
的方法? 通過dispatch
(分發)的方式。
// 以普通方式分發
this.$store.dispatch('incrementAsync')
// 以載荷形式分發
this.$store.dispatch('incrementAsync1', {
amount: 10
})
// 以對象形式分發
this.$store.dispatch({
type: 'incrementAsync2',
amount: 10
})
-
getters
:可以看做是Store
實例的計算屬性;用法與vue
的計算屬性一致。
getters
的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會被重新計算。
getters
只接受兩個參數state
、getters
。要是實現給getter
傳參,只能通過讓getter
返回一個函數。
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)
},
// 接收兩個參數
doneTodos1: (state, getters) => {
return getters.doneTodos.length
},
// 返回一個函數
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
}
})
總結
- 如果認真看完就會發現與官網給的核心概念的目錄順序不同,我建議看文檔的順序是先看
state
、mutation
、actions
,然后再看getters
、modules
,這樣相對容易理解。 - 詳情請移步 Vuex 官網