美文网首页
Vue2的源码学习3:mixin 原理的实现以及生命周期的调用

Vue2的源码学习3:mixin 原理的实现以及生命周期的调用

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

    开始

    前两节我们分别对Vue2中的响应式数据原理以及模板编译分别进行了总结整理,下面对Vue的mixin的实现和Vue的生命周期合并于调用进行总结整理。

    Vue.mixin

    Vue.mixin
    Vue中的mixin的方法也是开发中一个很常用的方法,特别是在组件封装中,我们可以依赖它实现方法的复用,之前在总结Vuex的源码的时候,在实现全局安装Vuex的方法,同样也依赖它实现的。
    https://juejin.im/post/5efdd3b45188252e47138a23

      Vue.mixin({
            beforeCreate(){
                //说明是根
                if(this.$options && this.$options.store)
                {
                    this.$store=this.$options.store;
    
                }
                else{
                    this.$store=this.$parent && this.$parent.$store;
                }
            }
      })
    

    实现

    思路

    mixin 的本质还是对象之间的合并,但是对不同对象和方法右不同的处理方式,对于普通对象,就是简单的对象合并类似于Object.assign,对于基础类型就是后面的覆盖前面的,而对于生命周期上的方法,相同的则是合并到一个数组中,调用的时候依次调用。

    代码实现

    • 定义mixin 方法
    import {  mergeOptions} from "./util/index.js";
    /*
       初始化全局的API
    */
    export function initGlobalApi(Vue){
            Vue.options={};
            Vue.mixin=function(mixin){
               this.options=mergeOptions(this.options,mixin);
               return this;
           }
    }
    
    • 合并对象的方法
    export function mergeOptions(parent,child){
        
          const options={} ;
           for(let key in parent)
           {
                mergeFields(key)
           }
           for(let key in child)
           {
               
                if(!parent.hasOwnProperty[key]){
                      mergeFields(key)
                }
           }
           /**
            * 合并属性
            * @param {*} key 
            */
    
           function mergeFields(key){
              
               //如果策略模式上存在
               if(strats[key]){
                     options[key]=strats[key](parent[key],child[key])
               }
        
               //如果都是对象 {a:11,b:2},{a:12,c:14} =>{a:12,b:2,c:14}
               else if(isReallyObject(parent[key]) && isReallyObject(child[key] ))
               {
                     options[key]={
                           ...parent[key],
                           ...child[key]
                      }
               }
               else if(child[key]){
                     options[key]=child[key]
               }
               else{
                   options[key]=parent[key];
               }
           }
           
           return options;
    
    }
    
    

    其实源码中合并的方法很复杂,包括对合并对象的响应式数据处理,还有组件中 minins的合并策略,如有兴趣,可查看源码中的options.js 文件。

    生命周期

    生命周期的合并

    Vue2 中有如下几个生命周期

        'beforeCreate',
        'created',
        'beforeMount',
        'mounted',
        'beforeUpdate',
        'updated',
        'beforeDestroy',
        'destroyed',
    

    每个组件都有自己的生命周期,组件之间生命周期的合并也是依赖Vue.mixin 实现的
    合并方法

    //存放策略(合并对象前会优先调用)
    let strats={
    }
    
    const LIFECYCLE_HOOKS =[
        'beforeCreate',
        'created',
        'beforeMount',
        'mounted',
        'beforeUpdate',
        'updated',
        'beforeDestroy',
        'destroyed',
    ]
    LIFECYCLE_HOOKS.forEach((hook)=>{
          strats[hook]=mergeHook;
    })
     /**
      * 合并生命周期的钩子
      * @param {*} parentValue 
      * @param {*} childValue 
      */
    function mergeHook(parentValue,childValue){
        //有子
        if(childValue){
            //有父
            if(parentValue)
            {
                //合并
                return parentValue.concat(childValue);
            }
            else{
                //返回
                  return [childValue];
            }
              
        }
        else{
             return parentValue;
        }
         
    }
    

    生命周期的调用

    调用方法

     export function callHook(vm,hook){
           const hookCallbacks=vm.$options[hook] ||[];
           for(let i=0;i<hookCallbacks.length;i++)
          {
              hookCallbacks[i].call(vm)
           }
     }
    
    

    调用

    beforeCreatecreated 为例,在实现响应式处理数据前后分别调用。

     Vue.prototype._init=function(options){
                 const vm=this;
                 //将参数挂载到 vm 上
                 vm.$options = mergeOptions(vm.constructor.options,options);
                 callHook(vm,'beforeCreate');
                 initState(vm);
                 callHook(vm,'created');
                if(vm.$options.el)
                {
                     this.$mount(vm.$options.el);
                }
            }
    

    测试

     Vue.mixin({
            name2:"sss",
            obj:{
                a:1,
                b:2
            },
            created:function(){
                 console.log('初始化了1');
             }
              
        })
        Vue.mixin({
            name3:"ssse",
            obj:{
                a:1,
                b:3,
                c:4
            },
            created:function(){
                 console.log('初始化了2');
             }
              
        })
         var vm=new Vue({
             el:"#app",
          
             created:function(){
                 console.log('初始化了3');
             }
              
            })
    

    结果

    image image

    结束

    简单了总结了一下Vue.mixin 方法和Vue 2的生命周期合并与调用,仅仅讲述的它的基本原理和简单实现。下一节整理总结Vue2依赖收集。

    链接

    相关文章

      网友评论

          本文标题:Vue2的源码学习3:mixin 原理的实现以及生命周期的调用

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