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

开始

前两节我们分别对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依赖收集。

链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352