第三章: Vuex旗下的Mutation

image

寫在前面

上一講「Vuex 旗下的 State 和 Getter」,告訴了我們?cè)趺慈ナ褂脗}(cāng)庫(kù) store 中的狀態(tài)數(shù)據(jù)。當(dāng)然,光會(huì)用肯定還不夠,大部分的應(yīng)用場(chǎng)景還得對(duì)這些狀態(tài)進(jìn)行操控,那么具體如何操控呢,這就是這一講要說(shuō)的重點(diǎn)。

只有 mutation 能動(dòng) State

更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似于事件:每個(gè) mutation 都有一個(gè)字符串的 事件類型 (type) 和 一個(gè) 回調(diào)函數(shù) (handler)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方,并且它會(huì)接受 state 作為第一個(gè)參數(shù):

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    // 事件類型 type 為 increment
    increment (state) {
      // 變更狀態(tài)
      state.count++
    }
  }
})

注意,我們不能直接 store.mutations.increment() 來(lái)調(diào)用,Vuex 規(guī)定必須使用 store.commit 來(lái)觸發(fā)對(duì)應(yīng) type 的方法:

store.commit('increment')

傳參

我們還可以向 store.commit 傳入額外的參數(shù):

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

// 調(diào)用
store.commit('increment', 10)

mutation 中的這個(gè)額外的參數(shù),官方給它還取了一個(gè)高大上的名字:載荷(payload)。說(shuō)實(shí)話,第一次在文檔中看到這個(gè)標(biāo)題「提交載荷」,真的就不想往下看了。

我們往往不是敗給了這些生澀的概念,而是敗給了自己內(nèi)心的恐懼。

大多數(shù)情況下,載荷是一個(gè)對(duì)象,能夠讓我們更加易讀:

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

關(guān)于提交的方式,有兩種:

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

// 2、整個(gè)對(duì)象都作為載荷傳給 mutation 函數(shù)
store.commit({
  type: 'increment',
  amount: 10
})

當(dāng)然,使用哪種方式?jīng)]有絕對(duì)的界限,純看自己的喜好,就我個(gè)人而言,還是比較傾向于使用第二種姿勢(shì),放在一起更實(shí)在。

修改規(guī)則

簡(jiǎn)單修改基礎(chǔ)類型的狀態(tài)數(shù)據(jù)倒是簡(jiǎn)單,沒(méi)什么限制,但是如果修改的是對(duì)象,那就要注意了。比如這個(gè)例子:

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

這個(gè)時(shí)候,我們?nèi)绻胍o student 添加一個(gè)年齡 age: 18 屬性,怎么辦呢?

是的,直接在 sex 下面把這個(gè)字段加上去不就行了,能這樣當(dāng)然最好了。但是如果我們要?jiǎng)討B(tài)的修改呢?那就得遵循 Vue 的規(guī)則了。如下:

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

以上就是給對(duì)象添加屬性的兩種方式,當(dāng)然,對(duì)于已添加的對(duì)象,如果想修改具體值的話,直接更改就是,比如 state.student.age=20 即可。

至于為什么要這樣,之前我們了解過(guò),因?yàn)?store 中的狀態(tài)是響應(yīng)式的,當(dāng)我們更改狀態(tài)數(shù)據(jù)的時(shí)候,監(jiān)視狀態(tài)的 Vue 組件也會(huì)自動(dòng)更新,所以 Vuex 中的 mutation 也需要與使用 Vue 一樣遵守這些規(guī)則。

使用常量

就是使用常量來(lái)替代 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 風(fēng)格的計(jì)算屬性命名功能來(lái)使用一個(gè)常量作為函數(shù)名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

可能有人會(huì)有疑問(wèn)啊,這樣做到底有啥用,還得多創(chuàng)建個(gè)類型文件,用的時(shí)候還要導(dǎo)入進(jìn)來(lái),不嫌麻煩嗎!

我們看看,mutation 是怎么調(diào)用的:store.commit('increment'),可以發(fā)現(xiàn),這里 commit 提交的方法 increment,是以字符串的形式代入的。如果項(xiàng)目小,一個(gè)人開(kāi)發(fā)的話倒還好,但是項(xiàng)目大了,編寫代碼的人多了,那就麻煩了,因?yàn)樾枰?commit 的方法一多,就會(huì)顯得特別混亂,而且以字符串形式代入的話,一旦出了錯(cuò),很難排查。

所以,對(duì)于多人合作的大項(xiàng)目,最好還是用常量的形式來(lái)處理 mutation,對(duì)于小項(xiàng)目倒是無(wú)所謂,想偷懶的隨意就好。

必須是同步函數(shù)

一定要記住,Mutation 必須是同步函數(shù)。為什么呢?

前面說(shuō)了,我們之所以要通過(guò)提交 mutation 的方式來(lái)改變狀態(tài)數(shù)據(jù),是因?yàn)槲覀兿胍鞔_地追蹤到狀態(tài)的變化。如果像下面這樣異步的話:

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

我們就不知道什么時(shí)候狀態(tài)會(huì)發(fā)生改變,所以也就無(wú)法追蹤了,這與 Mutation 的設(shè)計(jì)初心相悖,所以強(qiáng)制規(guī)定它必須是同步函數(shù)。

store.commit('increment')
// 任何由 "increment" 導(dǎo)致的狀態(tài)變更都應(yīng)該在此刻完成。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 寫在前面 上一講「Vuex 旗下的 State 和 Getter」,告訴了我們?cè)趺慈ナ褂脗}(cāng)庫(kù) store 中的狀態(tài)...
    大宏說(shuō)閱讀 29,745評(píng)論 11 89
  • ### store 1. Vue 組件中獲得 Vuex 狀態(tài) ```js //方式一 全局引入單例類 // 創(chuàng)建一...
    蕓豆_6a86閱讀 787評(píng)論 0 3
  • 安裝 npm npm install vuex --save 在一個(gè)模塊化的打包系統(tǒng)中,您必須顯式地通過(guò)Vue.u...
    蕭玄辭閱讀 3,038評(píng)論 0 7
  • Vuex是什么? Vuex 是一個(gè)專為 Vue.js應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件...
    蕭玄辭閱讀 3,232評(píng)論 0 6
  • Vuex 是什么? Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有...
    skycolor閱讀 929評(píng)論 0 1

友情鏈接更多精彩內(nèi)容