介紹
採用集中式儲存管理應用的所有元件的狀態, 就能實現元件間資料共享
實現
邏輯圖
從圖上有兩條線: 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