美文网首页
手把手Vuex(一)

手把手Vuex(一)

作者: 泰然自若_750f | 来源:发表于2020-07-04 07:59 被阅读0次

    Vuex的定义

    Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。主要包含如下几个部分。

    • state
    • mutations
    • actions
    • getters
    • modules

    Vuex 的安装

    在使用中我们通过 Vue.use(store) 的方式实现对Vuex的安装,然后我们就可以再每个组件中使用Vuex中的方法,下面我们看一下的它的实现。

    • 实现声明一个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 的实现

    state 是用来存储响应式数据的单一状态树

    • state中的数据是响应式的。
    • 通过 this.$store.state 访问其中的数据。

    原理实现

    class Store{
        constructor(options)
        {
            //state 将state 数据设置为响应式
            //this.state=options.state ||{}
            this._vm=new Vue({
                  data:options.state
        }
        // 获得state 
        get state(){
           return  this._vm
        }
    }
    

    将数据置为响应式有两种方案

    • 直接通过 new Vue({data:XXX})。
    • 通过Vue.observable(2.6新增)。

    getter 的实现

    • 调用方式:this.$store.getter.xxx,因此我们可以通过Object.defineProperty对xxx 属性进行数据劫持,一旦访问改属性,就执行相应的方法。
    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 数据设置为响应式
            //this.state=options.state ||{}
            this._vm=new Vue({
                  data:options.state
            })
            //设置 getters
            let getters=options.getters ||{};
            this.getters={};
            //getter 的核心实现
            forEach(getters,(key,fn)=>{
                  Object.defineProperty(this.getters,key,{
                      get:()=>{
                            return fn.call(this,this.state);
                      }
                  })
            })
    
            })
      
        }
       
    }
    
    

    mutation的实现

    mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。

    • 对传入的属性进行遍历订阅
    • 通过commit方法触发调用。

    核心就是一个发布订阅

    class Store{
        constructor(options)
        {
            //设置 mutations 依赖于 订阅 发布模式 
    
            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的实现。

    本质和mutation没有什么不同,同样也是一个发布订阅,就是在使用总一半用于处理异步请求。

       //
      forEach(actions,(key,fn)=>{
                this.actions[key]=(params)=>{
                    fn.call(this,this.state,params);
               }
               
            })
    //触发action调用
     dispatch=(type,params)=>{
            this.actions[type](params);
    
        }
    
    

    全部源码:

    class Store{
        constructor(options)
        {
            //state 将state 数据设置为响应式
            //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 依赖于 订阅 发布模式 
    
            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
    }
    

    结语

    至此我们实现了一个简易的Vuex,可以基本模拟Vuex的常用场景,但是还没有实现modules的实现,加入了module就变得复杂很多。以上代码就会有很大变动,但是核心原理没有改变,我们下一节继续探究modules的实现。本人小白,如有错误,请谅解,并欢迎指正

    下一节:https://juejin.im/post/5efe7cd3e51d45349d6c03b2

    相关文章

      网友评论

          本文标题:手把手Vuex(一)

          本文链接:https://www.haomeiwen.com/subject/rkvyqktx.html