标题:vue2生命周期详解在探索vue生命周期之前,我们先问一个问题:newVue()之后发生了什么?,当数据(data)发生变化时会发生什么?从上图可以看出生命周期流程图。newVue()之后,经历了以上几个阶段,即初始化阶段、模板编译阶段、挂载阶段、更新阶段、销毁阶段。那么每个阶段都做了一点点什么呢?在初始化阶段,先进行一些初始化操作,主要是给vue实例设置一些私有属性。运行生命周期钩子函数beforeCreate进入注入流程,流程属性,computed,methods,data,provide,inject,最后使用代理方式将这些属性挂载到实例中。在编译阶段运行创建的生命周期钩子函数生成渲染函数:如果有配置,直接使用配置好的渲染函数,如果没有,使用运行时编译器将模板编译成渲染函数。在mount阶段,运行生命周期钩子函数beforeMount创建一个Watcher并传入一个updeteComponent函数,updeteComponent会运行render函数,将render函数返回的vnode作为参数传递给_updete函数执行。//伪代码updateComponent(){_update(_render())}newWatcher(updateComponent)会在render函数执行过程中收集所有的依赖,以后依赖发生变化时会执行updateComponent函数。在执行_update的过程中,会触发patch函数。由于没有现成的虚拟DOM树,所以直接为当前虚拟DOM树的每个节点生成对应的elm属性,也就是真实的DOM。如果遇到创建组件实例的vnode,就会进入组件实例化过程,这个过程和vue实例过程一样,初始化阶段、编译阶段、挂载阶段同上。最后将创建的组件实例挂载到vnode的componentInstance属性中,以供复用。运行生命周期钩子函数mountedupdatephasedatachanges后,所有依赖该数据的watchers都会重新运行。watcher会被Scheduler放入nextTick运行。参考Vue数据响应式原理,即在微队列中,避免多个依赖数据同时改变后被多次执行。在更新之前运行生命周期钩子函数。updateComponent函数重新执行://伪代码updateComponent(){_update(_render())}newWatcher(updateComponent)render函数执行过程中,会先移除之前的依赖,新的依赖再次收集。以后,运行updateComponent函数时,依赖会发生变化。在执行update函数的过程中,会触发patch函数对新旧DOM树进行比较:比较两棵DOM树的节点时,有两种情况,分别是:普通html节点的比较会导致realnodes组件节点被创建、删除、移动、更新比较组件节点将导致组件被创建、删除、移动和更新。a)组件节点创建完成后,进入组件实例化过程,同上初始化阶段、编译阶段、挂载阶段。b)当旧组件节点被删除时,会调用旧组件的$destroy方法删除组件,会触发生命周期钩子函数beforeDestroy,然后递归调用组件的$destroy方法,再触发生命周期钩子函数destroyedc)组件更新时,相当于重新触发组件的updateComponent函数,进入渲染流程,运行update阶段更新的生命周期钩子函数。当组件被销毁时,会调用组件的$destroy方法来删除组件。这个方法会调用beforeDestroy和destroyedMethodVue.prototype.$destroy=function(){//这个属性标记当前实例是否正在被销毁if(vm._isBeingDestroyed){return}callHook(vm,'beforeDestroy')vm._isBeingDestroyed=true//removeselffromparentconstparent=vm.$parentif(parent&&!parent._isBeingDestroyed&&!vm.$options.abstract){remove(parent.$children,vm)}//...callHook复制代码(vm,'destroy')//...vm.$off()}执行完beforeDestroy方法后,从父组件实例的$children中删除当前组件实例if(parent&&!parent._isBeingDestroyed&&!vm...}leti=vm._watchers.lengthwhile(i--){vm._watchers[i].teardown()}if(vm._data.__ob__){vm._data.__ob__.vmCount--}vm._isDestroyed=truevm.__patch__(vm._vnode,null)执行销毁方法后,通过vm.$off()移除实例上的所有事件methodListener,展开回到原来的问题,newVue()之后发生了什么?,当数据(data)发生变化时会发生什么?毁灭呢?//main.jsimportVuefrom"vue";importAppfrom"./App.vue";Vue.config.productionTip=false;newVue({render:(h)=>h(App),beforeCreate(){console.log("vueinstancebeforeCreate");},created(){console.log("vueinstancecreated");},beforeMount(){console.log("vueinstancebeforeMount");},mounted(){console.log("vueinstancemounted",this);},beforeUpdate(){console.log("vueinstancebeforeUpdate");},updated(){console.log("vueinstanceupdate");},beforeDestroy(){console.log("vueinstancebeforeDestroy");},destroyed(){console.log("vueinstancedestroyed");},}).$mount("#app");//App<模板>
