手把手Vuex(一)

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)。本人小白,如有錯誤,請諒解,并歡迎指正

下一節(jié):https://juejin.im/post/5efe7cd3e51d45349d6c03b2

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

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