一、概述Vue的生命周期包括以下主要阶段:(1)初始化阶段初始化阶段包括创建新的Vue实例、初始化事件、初始化生命周期、初始化注射等;初始化阶段对应beforeCreate()和created()事件之前的阶段;(2)模板编译阶段模板编译阶段对应beforeMount()之前的阶段;(3)挂载阶段挂载阶段将实例挂载到指定的DOM上,并将模板渲染到真实的DOM上;mount阶段对应于mounted()之前的阶段;(4)销毁阶段销毁阶段从父组件中删除实例。2.初始化阶段Ⅰ。在初始化阶段,首先要做的是创建一个新的Vue实例。Vue类中所做的事情非常简单。Vue的定义是通过调用this._init(options)函数完成的。(1)this._init()函数从何而来?在Vue源码中的core/instance/init.js中,定义了一个函数initMixin()。在这个函数中,_init方法绑定了Vue的原型:Vue.prototype._init=function(options?:Object){//dosomething}(2)你在_init方法中做了什么?主要做了以下几件事:合并options属性,将合并后的值赋给$options挂载到vue实例上;初始化生命周期、事件、渲染、注入、数据等;适时调用trigger生命周期hook函数完成所有初始化工作后,会判断el是否传入,然后编译挂载模板if(vm.$options.el){vm.$mount(vm.$options.el)}if不带el选项,用户需要手动挂载vm.$mount()。(3)合并属性?mergeOptions方法将vue实例的构造函数上的选项与传入的选项合并;有几个关键点需要理解:构造函数的选项包括组件、过滤器、指令等几个空对象,并添加了一些内置组件;对于不同类型的选项有不同的合并策略。通过mergeField()方法合并它们:functionmergeField(key){conststrat=strats[key]||defaultStratoptions[key]=strat(parent[key],child[key],vm,key)}通过不同的策略合并父子选项中相同的属性;对于生命周期钩子函数的合并函数,结果是将同一个生命周期钩子函数合并到一个数组中。这样做是考虑到Vue的mixin在注入的时候,有可能在同一个生命周期中注入不同的函数,而这些函数需要被触发,所以存储在一个数组中。(4)callHook是如何执行的?先获取属性合并得到的对应钩子函数数组;遍历数组,将数组中的所有函数执行一次。二.在初始化阶段,实例创建完成后,会调用一些初始化函数。(1)initLifecycle()方法的内容很简单。主要是将一些属性设置为默认值挂在实例上,主要包括$parent和$root属性;(2)initEvents():初始化实例的事件系统(v-on,@...)initEvents():1.在实例上绑定_events是一个空对象(这里的_events是父组件绑定的事件到当前组件)2.判断父组件上是否有注册事件(也是父组件绑定到子组件的事件),如果有,则将父组件上的事件注册到子组件上组件-调用updateComponentListeners();updateComponentListeners():调用updateListeners()函数,并将addlisteners和add/remove两个方法传入;(target先设置为vm,为什么调用函数后设置为undefined?保留vm实例的引用)在理解updateListeners函数之前,先看看add和remove分别做了什么?*add()调用实例的$on方法,将通过$on传递的事件传入_events对象{eventName:eventFunction()...}*remove()调用实例的$off方法,可以通过代码可以看出$off的三种用法,第一种:清除所有事件,不传参;第二种:只传第一个参数,清空_events对象下的属性事件数组;第三个:传入两个A参数清除特定事件;updateListeners()主要做的是比较新传入的事件和原事件,如果有新的就调用add,如果原事件列表中存在但不存在则调用removeUninstall事件;(createFnInvoker部分不好理解:由于一个事件可能对应多个回调函数,所以这里对数组进行判断,依次调用多个回调函数。注意最后的赋值逻辑,invoker.fns=fns,每次执行invoker函数,都会从invoker.fns中取出回调函数返回给updateListeners。当我们第二次执行该函数时,判断是否cur!==old,那么只需要修改old.fns=cur,将之前绑定的involer.fns赋值为新的回调函数,并保持引用关系通过on[name]=old,保证事件回调只添加一次,然后修改其回调函数的引用即可。)模板解析阶段事件解析模板解析时,除了解析起始标签外,还会解析标签中的属性等,processAttrs方法,解析不同的属性,遇到v-on修饰符时,会调用addHandler()方法。addHandler()主要做了什么?首先,对于不同修饰符(capture、once等)的事件,在事件名称name上加上相应的符号,并进行特殊处理,以便后面生成render函数时可以识别不同的事件;然后根据modifier.native判断事件是Browser原生事件还是自定义事件,分别对应el.nativeEvents和el.events;最后将对应事件函数的字符串保存到对应的events[name]中。例如:
