vue之vuex

介紹:

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'
    ])
  }
}
以上則爲入門vuex需要學習的一些內容,更深入的瞭解則需老鐵們在項目中的實踐了,可到官網溜達溜達:https://vuex.vuejs.org/zh/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章