對vuex原理的理解

使用的源碼版本為3.5.1

定義

Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。

使用場景

它的優(yōu)勢用于解決下面兩個(gè)問題:

  1. 多個(gè)視圖依賴于同一狀態(tài)。
  2. 來自不同視圖的行為需要變更同一狀態(tài)。

解決方式是:

  • 全局單例集中管理
  • 數(shù)據(jù)單向流動

源碼架構(gòu)

vuex源碼架構(gòu)核心點(diǎn)兩個(gè):

  • 觀察者模式
  • 把state中的狀態(tài)處理成響應(yīng)式的

觀察者模式

我們定義的Action和Mutation都是具體的事件,會被vuex搜集保存起來

function installModule (store, rootState, path, module, hot) {

  module.forEachMutation((mutation, key) => {
    const namespacedType = namespace + key
    registerMutation(store, namespacedType, mutation, local)
  })

  module.forEachAction((action, key) => {
    const type = action.root ? key : namespace + key
    const handler = action.handler || action
    registerAction(store, type, handler, local)
  })
}
function registerMutation (store, type, handler, local) {
  const entry = store._mutations[type] || (store._mutations[type] = [])
  entry.push(function wrappedMutationHandler (payload) {
    handler.call(store, local.state, payload)
  })
}

function registerAction (store, type, handler, local) {
  const entry = store._actions[type] || (store._actions[type] = [])
  entry.push(function wrappedActionHandler (payload) {
    let res = handler.call(store, {
      dispatch: local.dispatch,
      commit: local.commit,
      getters: local.getters,
      state: local.state,
      rootGetters: store.getters,
      rootState: store.state
    }, payload)
    if (!isPromise(res)) {
      res = Promise.resolve(res)
    }
    if (store._devtoolHook) {
      return res.catch(err => {
        store._devtoolHook.emit('vuex:error', err)
        throw err
      })
    } else {
      return res
    }
  })
}

dispatch和commit的作用是發(fā)布事件

 // 只保留核心代碼
  dispatch (_type, _payload) {
    // check object-style dispatch
    const {
      type,
      payload
    } = unifyObjectStyle(_type, _payload)

    const action = { type, payload }
    const entry = this._actions[type]
    const result = entry.length > 1
      ? Promise.all(entry.map(handler => handler(payload)))
      : entry[0](payload)
 // 只保留核心代碼
  commit (_type, _payload, _options) {
    // check object-style commit
    const {
      type,
      payload,
      options
    } = unifyObjectStyle(_type, _payload, _options)

    const mutation = { type, payload }
    const entry = this._mutations[type]

    this._withCommit(() => {
      entry.forEach(function commitIterator (handler) {
        handler(payload)
      })
    })
  }

dispach發(fā)布事件,遍歷找到對應(yīng)的action處理,處理異步操作完成之后調(diào)用commit提交事件,遍歷找到對應(yīng)的mutation去處理(主要是修改state中數(shù)據(jù)狀態(tài)),這樣就完成了整個(gè)流程

響應(yīng)式原理

在store的構(gòu)造器中會調(diào)用resetStoreVM

 // 只保留核心代碼
function resetStoreVM (store, state, hot) {
  store._vm = new Vue({
    data: {
      $$state: state
    },
    computed
  })
}

核心是創(chuàng)建一個(gè)vue實(shí)例,利用vue響應(yīng)式原理把state的中的數(shù)據(jù)處理成響應(yīng)式的。
vue響應(yīng)式的原理可以看我的這篇文章:從源碼的角度分析Vue視圖更新和nexttick機(jī)制

參考:
http://www.itdecent.cn/p/d95a7b8afa06
https://vuex.vuejs.org/zh/guide/actions.html
https://tech.meituan.com/2017/04/27/vuex-code-analysis.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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