import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
? ? ? state: { count: 0 },
? ? ? mutations: {
? ? ? ? ? ? increment (state) {
? ? ? ? ? ? ? ? state.count++
? ? ? ? ? ? }
? ? ? }
})
以上就是一個最簡單的Vuex,每一個Vuex應用就是一個store,在store中包含組件中的共享狀態(tài)state和改變狀態(tài)的方法(暫且稱作方法)mutations。
vuex的核心是:state,getter,actions,mutations
1、state
state就是根據你項目的需求,自己定義的一個數據結構,里面可以放些通用的狀態(tài)。
const state = {
? openId:"",
? storeId:"",
? storeName:''
}
例如上面所寫的,這些狀態(tài)可以在各個頁面通過vuex訪問。如下:
this.$store.state.openId = "111"
之前我一直通過上面的方式來修改state里面的狀態(tài)值,行,肯定能用,但是好像官方并不建議我們這樣使用,而是建議使用mutations來改變state里面的值,因為不通過mutations改變state,狀態(tài)不會被同步。至于mutations下面會講到。
2、getter
getter怎么理解呢?通俗的理解可以認為是getter里的函數就是vuex里的計算屬性,類似于computed函數。
const store = new Vuex.Store({
? ? ? state: {
? ? ? ? ? ? count: 0
? ? ? },
? ? ? getters: {? // getters
? ? ? ? ? ? countAdd: function (state) {
? ? ? ? ? ? ? ? return state.count++
? ? ? ? ? ? }
? ? ? },
? ? ? mutations: {
? ? ? ? ? ? increment (state) {
? ? ? ? ? ? ? ? state.count++
? ? ? ? ? ? }
? ? ? }
})
getter函數怎么用呢?如上vuex里定義了一個getter函數countAdd。我們可以在vue文件里的computed計算屬性里引用,如下。
computed: {
? ? ...mapGetters{["countAdd"]}
? ? show:function(){
? ? ? ? ? alert("這個是測試頁面")
? ? }
}
這樣我們可以直接在vue頁面里取到countAdd的值{{countAdd}}即為1。可惜在我的項目里目前還沒用到getter,可能寫的少了,還沒理解其中的要義。
3、mutations
官方定義:更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。Vuex 中的 mutations 非常類似于事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態(tài)更改的地方,并且它會接受 state 作為第一個參數:
const store = new Vuex.Store({
? state: {
? ? count: 1
? },
? mutations: {
? ? increment (state) {
? ? ? // 變更狀態(tài)
? ? ? state.count++
? ? }
? }
})
你不能直接調用一個 mutation handler。這個選項更像是事件注冊:“當觸發(fā)一個類型為 increment 的 mutation 時,調用此函數。”要喚醒一個 mutation handler,你需要以相應的 type 調用 store.commit 方法:
store.commit('increment')
也可以向store.commit傳入第二參數,也就是mutation的payload:
mutaion: {
? ? increment (state, n) {
? ? ? ? state.count += n;
? ? }
}
store.commit('increment', 10);
但是有時候,單個傳入n可能并不能滿足我們的業(yè)務需要,這時候我們可以選擇傳入一個payload對象:
mutation: {
? ? increment (state, payload) {
? ? ? ? ? ? state.totalPrice += payload.price + payload.count;
? ? }
}
store.commit({
? ? type: 'increment',
? ? price: 10,
? ? count: 8
})
不例外,mutations也有映射函數mapMutations,幫助我們簡化代碼,使用mapMutations輔助函數將組件中的methods映射為store.commit調用。
import { mapMutations } from 'vuex'
export default {
? methods: {
? ? ...mapMutations({
? ? ? ? add: 'increment' // 映射 this.add() 為 this.$store.commit('increment')
? ? })
? }
}
這樣我們可以在vue文件里直接調用函數:this.add()而不用this.$store.commit('increment')這樣寫了,簡化了很多。
需要注意:Mutations必須是同步函數。
如果我們需要異步操作,Mutations就不能滿足我們需求了,這時候我們就需要Actions了。
4、action
Action 類似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接變更狀態(tài)。
Action 可以包含任意異步操作。
官方demo如下:
const store = new Vuex.Store({
? state: {
? ? count: 0
? },
? mutations: {
? ? increment (state) {
? ? ? state.count++
? ? }
? },
? actions: {
? ? increment (context) {
? ? ? context.commit('increment')
? ? }
? }
})
如果我在vue頁面里想用action,我們可以分發(fā) Action,Action 通過 store.dispatch 方法觸發(fā):
store.dispatch('increment')
Actions 支持同樣的載荷方式和對象方式進行分發(fā):
// 以載荷形式分發(fā)
store.dispatch('incrementAsync', {
? amount: 10
})
// 以對象形式分發(fā)
store.dispatch({
? type: 'incrementAsync',
? amount: 10
})
我們也可以運用其映射函數:mapActions
methods:{
? ? ...mapActions{[
? ? ? ? ? "add":"increment "http://函數命名不相同
? ? ? //? "increment ":"increment "http://函數命名相同
? ? ]}
}
調用:this.add()即可。相同時候調用:this.increment()
Modules
由于使用單一狀態(tài)樹,應用的所有狀態(tài)會集中到一個比較大的對象。當應用變得非常復雜時,store 對象就有可能變得相當臃腫。
為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割:
const moduleA = {
? state: { ... },
? mutations: { ... },
? actions: { ... },
? getters: { ... }
}
const moduleB = {
? state: { ... },
? mutations: { ... },
? actions: { ... }
}
const store = new Vuex.Store({
? modules: {
? ? a: moduleA,
? ? b: moduleB
? }
})
store.state.a // -> moduleA 的狀態(tài)
store.state.b // -> moduleB 的狀態(tài)
總結起來:mutation 只管存,你給我(dispatch)我就存;action只管中間處理,處理完我就給你,你怎么存我不管(所有的改變state狀態(tài)的都是mutation 來操作);Getter 我只管取,我不改的(類似計算屬性)。