幾十行程式碼實現一個vue的狀態管理
採用集中式儲存管理應用的所有元件的狀態, 就能實現元件間資料共享
實現
邏輯圖

從圖上有兩條線: Vue.use(vuec)
, 與 new Vuec.center(options)
第一條線 Vue.use(vuec)
安裝外掛
使用 Vue.use(vuec)
時, 會執行 vuec
的 install
方法,會注入引數 Vue
所以 vuec
是這樣的,
// index.js import {Center, install} from './center' export default {Center, install} 複製程式碼
Center
物件將例項化成 center
(下面再說),我們先看看 install
方法
// center.js let Vue // 全域性變數, 儲存install裡的Vue export function install (_Vue) { if (!Vue) { _Vue.mixin({ beforeCreate: applyMixin // 在beforeCreate鉤子上混入applyMixin函式 }) } Vue = _Vue } 複製程式碼
install
在 Vue
原型的 beforeCreate
混入 applyMixin
函式, 也就是說在生成每個 Vue
元件時,在它的生命週期 beforeCreate
鉤子上就會執行 applyMixin
方法
第二條線 new Vuec.center(options)
例項化 Center
物件
先看看使用者傳入的 options
, 下面例子
export default new Vuec.Center({ state: { name: 'liuyang' }, mutations: { changeName (state) { state.name = 'jike' } } }) 複製程式碼
上面程式碼會生成 center
例項, 該例項上應該包括: state
狀態, commit
方法提交變更等
// center.js export class Center { constructor (options= {}) { let center = this this.mutations = options.mutations observeState(center, options.state) } get state () {// 代理了this.$center.state的最終訪問值 return this._vm.$data.$$state } commit (_type, _payload) { this.mutations[_type](this.state, _payload) } } function observeState(center, state) { // 響應式state center._vm = new Vue({ data: { $$state: state } }) } 複製程式碼
在執行 new Vuec.Center({..})
時,就是執行 Center
的建構函式
-
首先執行
let center = this
, 定義center
儲存當前例項 -
接著執行
this.mutations = options.mutations
, 在例項center
上新增mutations
屬性, 值就是使用者輸入mutations
,按上面例子,
this.mutations
長成這樣this.mutations = { changeName (state) { state.name = 'jike' } } 複製程式碼
-
最後執行
observeState(center, options.state)
, 作用:讓center
例項的state
屬性指向options.state
並且是響應式的
function observeState(center, state) { // 響應式state center._vm = new Vue({// 利用Vue的響應系統,將state轉化成響應式 data: { $$state: state } }) } 複製程式碼
在 center
例項上新增 _vm
屬性, 值是一個 Vue
例項, 在該 Vue
例項的 data
下定義了 $$state
, 它的值是 options.state
使用者輸入的 state
; 結合上面的這段程式碼
// center.js export class Center { ...省略 get state () {// 代理了this.$center.state的最終訪問值 return this._vm.$data.$$state } ...省略 } 複製程式碼
所以我們在元件中訪問 center.state
其實就是訪問 center._vm.$data.$$state
OK, center
就構建好了
建立 Vue
元件
使用者輸入
import Vue from 'vue' import App from './App' import router from './router' import center from './center' new Vue({ el: '#app', router, center, // 構建好的center例項 template: '<App/>', components: {App} }) 複製程式碼
在 beforeCreate
生命週期時會觸發上面混入的 applyMixin
函式
// mixins.js export default function applyMixin() { vuecInit.call(this) // } function vuecInit () { const options = this.$options // vue的例項化是從外往內, 所以父元件的$center一定是options的center this.$center = options.parent?options.parent.$center: options.center } 複製程式碼
applyMixin
裡會執行 vuecInit.call(this)
, 這裡的 this
指向當前元件的例項,
接著看 vuecInit
, 定義了 options
等於使用者輸入選項,因為先建立根元件, 所以根元件 this.$center
的值的引用就是我們在 new Vue({..center})
時傳入的 center
例項, 下面所有元件都指向它
OK, 你就可以在元件裡使用 this.$center
訪問了
commit變更
// center.js export class Center { ... 省略 commit (_type, _payload) { this.mutations[_type](this.state, _payload) } } 複製程式碼
通常我們變更時: this.$center.commit('changeName', 'jike')
, 這樣的話, this.mutations[_type]
就是對應方法函式, 往該函式裡傳入 state
以及 payload
,
舉上面的例子
// this.mutations[_type] , _type = 'changeName', payload= 'jike' this.mutations = { changeName (state, payload) { state.name = payload } } 複製程式碼
說明
上面只是一個簡單的狀態管理, 還有很多地方沒有實現: actions
非同步變更, getters
函式, modules
模組分割, 輔助函式 mapState..
等
原始碼地址: github