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

2020-07-12  本文已影响0人  泰然自若_750f

开始

前两节我们分别对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,对于基础类型就是后面的覆盖前面的,而对于生命周期上的方法,相同的则是合并到一个数组中,调用的时候依次调用。

代码实现

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依赖收集。

链接

上一篇下一篇

猜你喜欢

热点阅读