介紹:
Vuex是一個專門爲vue應用而生的狀態管理模式,類似於flux、redux。目的是爲了解決組件間數據狀態的交互,其實質就是一個js對象。同時還能對數據進行有效的全局單例模式管理。
store:
1、Vuex中的store是響應式的,當其發生改變時,組件中使用到store的數據也會相應的進行更新。
2、不能直接對store進行操作,得通過唯一的途徑(commit)mutation改變store中的狀態。
首先需要實例化一個Store,同時需注入到vuex中:
//store.js
import Vue form 'vue'
import Vuex from 'vuex'
Vue.use(Vuex) //將vuex注入到vue中
const store = new Vuex.Store({
state: {
count: 1
}
})
export default store
//main.js
import Vue from 'vue'
import store from './store'
new Vue({
el: '#app',
store
})
store.state:
完成之後即可在組件中查看到store並在computed屬性中對數據進行監聽,vuex還提供了mapState函數可以store中的state快速獲取:
//home.vue
export default {
created() {
console.log(this.$store.state)
},
computed: {
count() {
return this.$store.state.count
}
}
}
//homve.vue
import { mapState } from 'vuex'
export default {
created() {
console.log(this.$store.state)
},
computed: {
...mapState(['count']),
...mapState({
fnCount: state => state.count, // 箭頭函數可使代碼更簡練
myCount: 'count', // 傳字符串參數 'count' 等同於 `state => state.count`
fn5Count: function(state){ // 爲了能夠使用 `this` 獲取局部狀態,必須使用常規函數
return this.myAge + state.count
}
})
}
}
store.getters:
有時需要對state中的數據進行處理(例如過濾、篩選等)需要些相同的邏輯函數,而在每個組件中引入處理函數又顯得過於冗餘,getters就派上用場了。就像計算屬性一樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被重新計算。
Getter 接受 state 作爲其第一個參數,第二個參數爲整個getters對象,可通過返回一個函數進行傳參:
//store.js
import Vuex from 'vuex'
const store = new Vuex.Store({
state: {
arr: ['a', 'b', 'c', 'd']
},
getters: {
findState: (state, getters) => (id)=> state.arr.find(i => i === id)
}
})
export default store
//home.vue
export default {
created(){
console.log(this.$store.getters.findState('c')) //'c'
}
}
輔助函數:mapGetters(用法類似於mapState)
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['findState']),
...mapGetters({
findState2: 'findState' // 把 `this.doneCount` 映射爲 `this.$store.getters.doneTodosCount`
})
}
}
store.mutations:
更改store中的狀態的唯一方法是mutations,接受state作爲第一個參數,需要store.commit方法調用,第二個參數爲可傳
//store.js
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
plus(state, param){
state += param.n
}
}
})
//home.vue
this.$store.commit('plus', { n: 20 })
//另一種調用風格
this.$store.commit({
type: 'plus',
n: 20
})
mutations必須是同步函數,任何在回調函數中進行的狀態的改變都是不可追蹤的。
輔助函數mapMutations(用法與mapGetters類同),其爲方法調用,寫在methods中:
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations(['plus']),
...mapMutations({
add: 'plus'
})
}
}
store.actions:
actions類似於mutations:
1、actions提交的是mutations,而不是直接變更store的狀態
2、actions可以包含任意異步操作
第一個參數是與store擁有相同的方法和屬性的context對象,可用es6的參數解構提取方法,通過dispath調用actions的方法,與調用commit類同,可以在actions用dispath調用另一個actions,也可與async/await結合用於獲取數據存儲到state中:
const store = new Vuex.Store({
state: {
name: 'lzccheng',
data: ''
},
mutations: {
changeName(state, param) {
state.name = param
},
setData(state, data) {
state.data = data
}
},
actions: {
async getData({ commit }) {
return await axios.get(API).then(res => commit('setData', res.data))
},
async actonsChangeName({ commit, dispath, state }, param){
commit('changeName', param)
await dispath('getData')
console.log(state.data)
}
}
})
//home.vue
this.$store.dispath('actionsChangeName', 'my name is lzccheng')
輔助函數:mapActions(與mapMutatios類似)
//home.vue
import { mapActions } from 'vuex'
export default {
methods: {
...mapActions(['actionsChangeName']),
...mapActions({
change: 'actionsChangeName'
})
}
}
store.module:
當一個應用比較大的時候,store的狀態就會變得臃腫,而module則可以將這些狀態分成更小的層級,可以更好地進行管理、劃分。
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
state: {...},
actions: {...},
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的狀態
store.state.b // -> moduleB 的狀態
局部actions中想獲取根的state,可在context中解構rootState值,調用根的actions或mutations可在dispath、commit中加入第三個參數{root:true}
actioins: {
someActions({ commit, dispath, state, getters, rootState, rootGetters }) {
console.log(rootState, rootGetters )
commit('mutations') //調用局部的mutations
commit('Mutations', null, { root: true }) //調用根的mutations
dispath('Actions') //調用局部的actions
dispath('Actions', null, { root: true }) //調用根的actions
}
}
局部getters:如果你希望使用全局 state 和 getter,rootState 和 rootGetter 會作爲第三和第四參數傳入 getter,也會通過 context 對象的屬性傳入 action。
getters: {
// 在這個模塊的 getter 中,`getters` 被局部化了
// 你可以使用 getter 的第四個參數來調用 `rootGetters`
someGetter (state, getters, rootState, rootGetters) {
getters.someOtherGetter // -> 'foo/someOtherGetter'
rootGetters.someOtherGetter // -> 'someOtherGetter'
},
someOtherGetter: state => { ... }
}
module的命名空間(namespace):
默認情況下,模塊內部的 action、mutation 和 getter 是註冊在全局命名空間的——這樣使得多個模塊能夠對同一 mutation 或 action 作出響應。
如果希望你的模塊具有更高的封裝度和複用性,你可以通過添加 namespaced: true 的方式使其成爲帶命名空間的模塊。當模塊被註冊後,它的所有 getter、action 及 mutation 都會自動根據模塊註冊的路徑調整命名。
啓用了命名空間的 getter 和 action 會收到局部化的 getter,dispatch 和 commit。換言之,你在使用模塊內容(module assets)時不需要在同一模塊內額外添加空間名前綴。更改 namespaced 屬性後不需要修改模塊內的代碼。
帶命名空間的綁定函數
當使用 mapState, mapGetters, mapActions 和 mapMutations 這些函數來綁定帶命名空間的模塊時,寫起來可能比較繁瑣:
computed: {
...mapState({
a: state => state.some.nested.module.a,
b: state => state.some.nested.module.b
})
},
methods: {
...mapActions([
'some/nested/module/foo', // -> this['some/nested/module/foo']()
'some/nested/module/bar' // -> this['some/nested/module/bar']()
])
}
對於這種情況,你可以將模塊的空間名稱字符串作爲第一個參數傳遞給上述函數,這樣所有綁定都會自動將該模塊作爲上下文。於是上面的例子可以簡化爲:
computed: {
...mapState('some/nested/module', {
a: state => state.a,
b: state => state.b
})
},
methods: {
...mapActions('some/nested/module', [
'foo', // -> this.foo()
'bar' // -> this.bar()
])
}
而且,你可以通過使用 createNamespacedHelpers 創建基於某個命名空間輔助函數。它返回一個對象,對象裏有新的綁定在給定命名空間值上的組件綁定輔助函數:
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
export default {
computed: {
// 在 `some/nested/module` 中查找
...mapState({
a: state => state.a,
b: state => state.b
})
},
methods: {
// 在 `some/nested/module` 中查找
...mapActions([
'foo',
'bar'
])
}
}