Vuex的定義
Vuex是一個專為 Vue.js 應用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應用的所有組件的狀態(tài),并以相應的規(guī)則保證狀態(tài)以一種可預測的方式發(fā)生變化。主要包含如下幾個部分。
- state
- mutations
- actions
- getters
- modules
Vuex 的安裝
在使用中我們通過 Vue.use(store) 的方式實現(xiàn)對Vuex的安裝,然后我們就可以再每個組件中使用Vuex中的方法,下面我們看一下的它的實現(xiàn)。
- 實現(xiàn)聲明一個install方法,這樣Vue.use 就可以調用。
- Vue.use 會傳入Vue,通過Vue.mixin 在Vue生命周期beforeCreate 為每個組件注入store。
//安裝的方法
const install=(_Vue)=>{
Vue=_Vue;
//為每個組件注入
Vue.mixin({
beforeCreate(){
//說明是根
//this.$options.store 因為在main.js 中 new Vue({store})
if(this.$options && this.$options.store)
{
this.$store=this.$options.store;
}
//子組件就從父組件取
else{
this.$store=this.$parent && this.$parent.$store;
}
}
})
}
state 的實現(xiàn)
state 是用來存儲響應式數(shù)據(jù)的單一狀態(tài)樹
- state中的數(shù)據(jù)是響應式的。
- 通過 this.$store.state 訪問其中的數(shù)據(jù)。
原理實現(xiàn)
class Store{
constructor(options)
{
//state 將state 數(shù)據(jù)設置為響應式
//this.state=options.state ||{}
this._vm=new Vue({
data:options.state
}
// 獲得state
get state(){
return this._vm
}
}
將數(shù)據(jù)置為響應式有兩種方案
- 直接通過 new Vue({data:XXX})。
- 通過Vue.observable(2.6新增)。
getter 的實現(xiàn)
- 調用方式:this.$store.getter.xxx,因此我們可以通過Object.defineProperty對xxx 屬性進行數(shù)據(jù)劫持,一旦訪問改屬性,就執(zhí)行相應的方法。
const forEach=(obj,callBack)=>
{
if(typeof obj!=='object' || obj===null)
{
return [];
}
Object.keys(obj).forEach(key=>{
callBack(key,obj[key])
});
}
class Store{
constructor(options)
{
//state 將state 數(shù)據(jù)設置為響應式
//this.state=options.state ||{}
this._vm=new Vue({
data:options.state
})
//設置 getters
let getters=options.getters ||{};
this.getters={};
//getter 的核心實現(xiàn)
forEach(getters,(key,fn)=>{
Object.defineProperty(this.getters,key,{
get:()=>{
return fn.call(this,this.state);
}
})
})
})
}
}
mutation的實現(xiàn)
mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數(shù) (handler)。
- 對傳入的屬性進行遍歷訂閱
- 通過commit方法觸發(fā)調用。
核心就是一個發(fā)布訂閱
class Store{
constructor(options)
{
//設置 mutations 依賴于 訂閱 發(fā)布模式
let mutations=options.mutations||{};
this.mutations={};
forEach(mutations,(key,fn)=>{
this.mutations[key]=(params)=>{
fn.call(this,this.state,params);
}
})
}
commit=(name,params)=>{
this.mutations[name](params)
}
}
action的實現(xiàn)。
本質和mutation沒有什么不同,同樣也是一個發(fā)布訂閱,就是在使用總一半用于處理異步請求。
//
forEach(actions,(key,fn)=>{
this.actions[key]=(params)=>{
fn.call(this,this.state,params);
}
})
//觸發(fā)action調用
dispatch=(type,params)=>{
this.actions[type](params);
}
全部源碼:
class Store{
constructor(options)
{
//state 將state 數(shù)據(jù)設置為響應式
//this.state=options.state ||{}
this._vm=new Vue({
data:options.state
})
//設置 getters
let getters=options.getters ||{};
this.getters={};
forEach(getters,(key,fn)=>{
Object.defineProperty(this.getters,key,{
get:()=>{
return fn.call(this,this.state);
}
})
})
//設置 mutations 依賴于 訂閱 發(fā)布模式
let mutations=options.mutations||{};
this.mutations={};
forEach(mutations,(key,fn)=>{
this.mutations[key]=(params)=>{
fn.call(this,this.state,params);
}
})
//配置 action
this.actions={};
let actions=options.actions ||{};
forEach(actions,(key,fn)=>{
this.actions[key]=(params)=>{
fn.call(this,this.state,params);
}
})
//對 modules 進行收集
var modules=new ModuleCollection(options);
console.log(modules);
}
get state(){
return this._vm
}
commit=(name,params)=>{
this.mutations[name](params)
}
dispatch=(type,params)=>{
this.actions[type](params);
}
}
//安裝的方法
const install=(_Vue)=>{
Vue=_Vue;
//為每個組件注入
Vue.mixin({
beforeCreate(){
//說明是根
if(this.$options && this.$options.store)
{
this.$store=this.$options.store;
}
else{
this.$store=this.$parent && this.$parent.$store;
}
}
})
}
//必須到處install 方法
export default{
install,
Store
}
結語
至此我們實現(xiàn)了一個簡易的Vuex,可以基本模擬Vuex的常用場景,但是還沒有實現(xiàn)modules的實現(xiàn),加入了module就變得復雜很多。以上代碼就會有很大變動,但是核心原理沒有改變,我們下一節(jié)繼續(xù)探究modules的實現(xiàn)。本人小白,如有錯誤,請諒解,并歡迎指正