挑戰全網最幽默的Vuex系列教程:第三講 Vuex旗下的Mutation

寫在前面

上一講「Vuex 旗下的 State 和 Getter」,告訴了咱們怎麼去使用倉庫 store 中的狀態數據。固然,光會用確定還不夠,大部分的應用場景還得對這些狀態進行操控,那麼具體如何操控呢,這就是這一講要說的重點。前端

只有 mutation 能動 State

**更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation。**Vuex 中的 mutation 很是相似於事件:每一個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是咱們實際進行狀態更改的地方,而且它會接受 state 做爲第一個參數:vue

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    // 事件類型 type 爲 increment
    increment (state) {
      // 變動狀態
      state.count++
    }
  }
})
複製代碼

注意,咱們不能直接 store.mutations.increment()來調用,Vuex 規定必須使用 store.commit 來觸發對應 type 的方法:vuex

store.commit('increment')
複製代碼

傳參

咱們還能夠向 store.commit 傳入額外的參數:api

mutations: {
  increment (state, n) {
    state.count += n
  }
}
複製代碼

// 調用 store.commit('increment', 10) mutation 中的這個額外的參數,官方給它還取了一個高大上的名字:載荷(payload)。說實話,第一次在文檔中看到這個標題**「提交載荷」**,真的就不想往下看了。bash

咱們每每不是敗給了這些生澀的概念,而是敗給了本身心裏的恐懼。架構

大多數狀況下,載荷是一個對象,可以讓咱們更加易讀:框架

mutations: { increment (state, payload) { state.count += payload.amount } } 關於提交的方式,有兩種:異步

// 一、把載荷和type分開提交
store.commit('increment', {
  amount: 10
})

// 二、整個對象都做爲載荷傳給 mutation 函數
store.commit({
  type: 'increment',
  amount: 10
})
複製代碼

固然,使用哪一種方式沒有絕對的界限,純看本身的喜愛,就我我的而言,仍是比較傾向於使用第二種姿式,放在一塊兒更實在。函數

修改規則

簡單修改基礎類型的狀態數據卻是簡單,沒什麼限制,可是若是修改的是對象,那就要注意了。好比這個例子:學習

const store = new Vuex.Store({
  state: {
    student: {
      name: '小明',
      sex: '女'
    }
  }
})
複製代碼

這個時候,咱們若是想要給 student 添加一個年齡age: 18屬性,怎麼辦呢?

是的,直接在 sex 下面把這個字段加上去不就好了,能這樣固然最好了。可是若是咱們要動態的修改呢?那就得遵循 Vue 的規則了。以下:

mutations: {
  addAge (state) {
    Vue.set(state.student, 'age', 18)
    // 或者:
    // state.student = { ...state.student, age: 18 }
  }
}
複製代碼

以上就是給對象添加屬性的兩種方式,固然,對於已添加的對象,若是想修改具體值的話,直接更改就是,好比state.student.age=20 便可。

至於爲何要這樣,以前咱們瞭解過,由於 store 中的狀態是響應式的,當咱們更改狀態數據的時候,監視狀態的 Vue 組件也會自動更新,因此 Vuex 中的 mutation 也須要與使用 Vue 同樣遵照這些規則。

使用常量

就是使用常量來替代 mutation 事件的名字。

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

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 使用 ES2015 風格的計算屬性命名功能來使用一個常量做爲函數名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})
複製代碼

可能有人會有疑問啊,這樣作到底有啥用,還得多建立個類型文件,用的時候還要導入進來,不嫌麻煩嗎!

咱們看看,mutation 是怎麼調用的:store.commit('increment'),能夠發現,這裏 commit 提交的方法increment,是以字符串的形式代入的。若是項目小,一我的開發的話倒還好,可是項目大了,編寫代碼的人多了,那就麻煩了,由於須要 commit 的方法一多,就會顯得特別混亂,並且以字符串形式代入的話,一旦出了錯,很難排查。

因此,對於多人合做的大項目,最好仍是用常量的形式來處理 mutation,對於小項目卻是無所謂,想偷懶的隨意就好。

必須是同步函數

必定要記住,Mutation 必須是同步函數。爲何呢?

前面說了,咱們之因此要經過提交 mutation 的方式來改變狀態數據,是由於咱們想要更明確地追蹤到狀態的變化。若是像下面這樣異步的話:

mutations: {
  someMutation (state) {
    api.callAsyncMethod(() => {
      state.count++
    })
  }
}
複製代碼

咱們就不知道何時狀態會發生改變,因此也就沒法追蹤了,這與 Mutation 的設計初心相悖,因此強制規定它必須是同步函數。

store.commit('increment')
// 任何由 "increment" 致使的狀態變動都應該在此刻完成。
複製代碼

寫在最後

這一講相對來講應該仍是比較好理解的。對於官方我以爲比較難理解的,我都儘可能用通俗易懂的示例來進行分析,來加深你們的理解,可是不知道效果如何。若是對你們有幫助,歡迎點贊和轉載,註明出處便可。

轉載聲明:

做者:大宏說 連接:www.jianshu.com/p/64727454f…

後記

以上就是胡哥今天給你們分享的內容,喜歡的小夥伴記得點贊收藏呀,關注胡哥有話說,學習前端不迷路,歡迎多多留言交流...

胡哥有話說,一個有技術,有情懷的胡哥!現任京東前端攻城獅一枚。 胡哥有話說,專一於大前端技術領域,分享前端系統架構,框架實現原理,最新最高效的技術實踐!

相關文章
相關標籤/搜索