[源碼學習] Vuex

原文連接vue

Vuex 做爲 Vue 官方的狀態管理架構,借鑑了 Flux 的設計思想,在大型應用中能夠理清應用狀態管理的邏輯。爲了更清楚的理解它的原理和實現,仍是從源碼開始讀起吧。總共 1000 多行的代碼,讀起來也相對輕鬆。vuex

cloc src/

------------------------------------------------------------------
Language   files          blank        comment         code
------------------------------------------------------------------
JavaScript   5             53            141            389
------------------------------------------------------------------
SUM:         5             53            141            389
------------------------------------------------------------------

cloc test/

------------------------------------------------------------------
Language   files          blank        comment         code
------------------------------------------------------------------
JavaScript   5             62             30            793
------------------------------------------------------------------
SUM:         5             62             30            793
------------------------------------------------------------------

結構梳理

先拋開 middlewares,Vuex 的主要源碼一共有三個文件:shell

file intro
index.js Class Store, install,...
override.js 初始化 Vuex
util.js 相關 util(用到了 getWatcher 和 getDeep)

Store

咱們使用 Store 建立 Vuex 的實例並傳遞給 Vue 的根組件。主要包含了 statemutationStore 建立了一個 datastate 的 Vue 實例,使用了 ES6 Class 的 getset 對 state 作了映射,對 state 的從新 set 固然是不容許的,get 則映射到了 this._vm._data緩存

Store 提供了 dispatch 方法來完成對 state 的修改,和想象中的差很少,在 _mutations 裏找到對應 type 的 mutation,參數併入 this.state 傳參調用。架構

override

做爲一個 Vue 的插件,Vuex 須要被這樣引入:ide

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

Vue 的插件應當有一個公開方法 install。這個方法的第一個參數是 Vue 構造器。 Vuex 的 install 中,在保證單次調用的狀況下,調用 override 對 Vue 構造器進入了注入。函數

override 中對 Vue.prototype._init 注入了 vuexInitvuexInit 會在每一個 instance 的 init hook 中調用。this

第一步是綁定 store, Vuex 會尋找 options 中的 store 做爲實例的 $store,在不存在時則以遞歸的方式尋找父組件中的 $store,所以在 Vuex 的項目中,store 只須要在根組件中注入便可。spa

第二步是處理 vuex, 分別處理其中的 gettersactions, 以 example/counter/Counter.vue 爲例:prototype

getters

Vuex 用 Object.defineProperty 爲每一個 getter 在 vm 上綁定了 data,特別的是 getter 做爲單向僅 get 數據流,並不能被 set,因此對應的 setter 爲報錯用的空函數。而 getter 的原理相似於 computed getter,特別的是使用了 store 的 uniqueId 爲標識作了緩存,這樣同一個 getter 在全部組件中都會使用相同的 watcher。

setter

Action 相對要簡單一些,以 $store 做爲 action 第一個參數,並將 action 綁定在 instance 上。造成了一個閉環,讓 action 訪問到 store。

總結

Vuex 源碼上粗略的分析基本就到這裏了,其實不少地方的代碼都很值得細細研究,好比 Store 中的 middlewares 能夠完成一些神奇的事情,這裏就不一一分析了,畫了一張圖,按源碼的思路大概表達下數據流的意思。O(∩_∩)O

+-----------+
      |           |
      |   Store   +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+
      |           |                                   v
      |-----------|                                   v
      |   state   <<<<<<+                             v
      |-----------|     ^                             v
+>>>>>- distapatch ->>>>+                             v
^     +-----------+                                   v
^                                                     v
^                          +--------------------+     v
^                          |                    |     v
^                          |     Component      |     v
^                          |                    |     v
^                          |--------------------|     v
^                    +<<<<<-----  $store  <------<<<<<+
^                    v     |--------------------|
^                    v     |  vuex: {           |
^                    v     |                    |
^                    +>>>>>----- getters: {},   |
^                          |                    |
+<<<<<<<<<<<<<<<<<<<<<<<<<<----- actions: {}    |
                           |                    |
                           |  }                 |
                           +--------------------+
相關文章
相關標籤/搜索