1. 程式人生 > 其它 >vuex中store 的mutation

vuex中store 的mutation

技術標籤:wed前端vue

vuex中store 的mutation

1.mutation

官方解釋mutation:

更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似於事件:每個 mutation 都有一個字串的 事件型別 (type) 和 一個 回撥函式 (handler)。這個回撥函式就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個引數

官方是建議我們通過mutation來實現更改store中的state的資料,而非在元件中直接使用 s t o r e . s t a t e . d a t a = x x x 來 直 接 進 行 更 改 。 通 過 m u t a t i o n 來 更 改 數 據 的 操 作 會 被 捕 獲 到 , 而 直 接 使 用 store.state.data=xxx來直接進行更改。通過mutation來更改資料的操作會被捕獲到,而直接使用

store.state.data=xxxmutation使store.state.data=xxx這種方式更的資料是無法被捕獲的,如果發生錯誤,將無法定位到是哪個元件的操作導致錯誤發生,所以官方說更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。

圖示:

上網找到 一個很不錯的圖

70

流程:

  • 繞過Actions(mutation必須是同步操作,Devtools才能追蹤變數)
  1. 使用者觸發事件
  2. 在事件處理中通過commit()提交對應的mutation
  3. mutation中對state進行修改
  4. state修改後響應系統更新檢視
  • 不繞過Actions(Action 可以包含任意非同步操作)
  1. 使用者觸發事件
  2. 在事件處理中通過dispatch()提交對應的Actions
  3. 在Actions中通過commit()提交對應的mutation
  4. mutation中對state進行修改
  5. state修改後響應系統更新檢視

解析:

當我們只有同步操作的時候,官方允許我們在元件中直接提交mutation,而不經過Actions,但是如果我們的操作包含非同步操作的時候,我們必須通過Actions來非同步提交mutation,從而實現非同步操作,這樣才能讓Devtools可以捕獲變數更改。

2.初次使用

const store = new Vuex.
Store
({ state: { count: 1 }, mutations: { increment (state) { // 變更狀態 state.count++ }, incrementNum (state,num) { // 通過提交載荷傳遞過來的num state.count+=num } } }) //在元件中定義一個方法通過$store.commit('increment')來進行提交 methods:{ increment(){ this.$store.commit('increment') }, incrementNum(num){ this.$store.commit('increment',num) } }

3.提交載荷

mutations接受commit傳遞過來的引數,這個引數叫做payload(提交載荷),我們可以通過payload來實現資料的傳遞。

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

store.commit('increment', {
  amount: 10
})

4.物件風格的提交方式

store.commit()提供了另一種提交風格,store.commit()允許以物件的風格進行提交,這個風格跟vue很切合,物件宣告形式。

store.commit({
  type: 'increment',       //對應commit第一個引數,也就是事件型別
  amount: 10			//傳遞的引數payload
})

使用

mutations: {
  increment (state, payload) {    //物件提交方式,payload是提交載荷
    state.count += payload.amount
  }
}

5.Mutation 需遵守 Vue 的響應規則

Vuex 的 store 中的狀態是響應式的,所以Vuex 中的 mutation 也需要與使用 Vue 一樣遵守一些注意事項。

新增操作

//錯誤的示範
state.info['address']='北京'


//正確的示範
Vue.set(state.info,'address','北京')
//vue官方說以新物件替換老物件是遵守 Vue 的響應規則
//響應系統能捕獲全新的物件資料
state.info = {//一個全新的物件}

第一個示範雖然是給state中的info添加了一個key value,但是這種新增操作是繞過了vue的響應式系統的,所以vue並沒有將新新增的key value追加到響應系統裡面,所以檢視是不會動態跟新新新增的資料。

而第二種示範,是通過vue的響應式系統進行變數的追加,所以vue能監控到變數的變化,從而對檢視做出響應和跟新。

刪除操作

刪除操作同理

Vue.delete(state.info,'address')

6.用常量替代Mutation事件型別

從上面的程式碼可以看出,我在使用store.commit的時候後面都是通過字串的形式來指定commit的mutation。而官方建議是將這種mutation 事件型別進行一個抽離,將這些mutation的名字定義到一個專門儲存的單獨檔案種,這樣做抽離,使得整個APP的mutatio易於管理,也使得專案結構清晰。

使用常量替代 mutation 事件型別在各種 Flux 實現中是很常見的模式。這樣可以使 linter 之類的工具發揮作用,同時把這些常量放在單獨的檔案中可以讓你的程式碼合作者對整個 app 包含的 mutation 一目瞭然:

官方建議的操作如下:

先將建立一個mutation-types.js,裡面儲存定義的mutation 事件型別

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
//定義什麼mutation,先將事件型別(名字)寫這裡

使用的時候

// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    /*
    	官方是用這種風格來命名的:
    	[SOME_MUTATION] (state) {} 
    	---等價轉變--->SOME_MUTATION(state) {}
    */
      // 我們可以使用 ES2015 風格的計算屬性命名功能來使用一個常量作為函式名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})
    
    
//其他元件commit時
import { SOME_MUTATION } from './mutation-types'
                             ...
store.commit(SOME_MUTATION)

7.Mutation 必須是同步函式

官方是這樣解釋的:

一條重要的原則就是要記住 mutation 必須是同步函式。為什麼?請參考下面的例子:

mutations: {
  someMutation (state) {
    api.callAsyncMethod(() => {
      state.count++
    })
  }
}

現在想象,我們正在 debug 一個 app 並且觀察 devtool 中的 mutation 日誌。每一條 mutation 被記錄,devtools 都需要捕捉到前一狀態和後一狀態的快照。然而,在上面的例子中 mutation 中的非同步函式中的回撥讓這不可能完成:因為當 mutation 觸發的時候,回撥函式還沒有被呼叫,devtools 不知道什麼時候回撥函式實際上被呼叫——實質上任何在回撥函式中進行的狀態的改變都是不可追蹤的。

所以我們為了能夠實現非同步操作,我們需要藉助Actions來實現,在Actions通過非同步提交 mutation從而實現非同步操作,Action 可以包含任意非同步操作,Action 提交的是 mutation,而不是直接變更狀態。