生命周期能够分为四个阶段,初始化阶段,模板编译阶段,挂载阶段,已挂载和卸载阶段。html
render函数选项 > template参数 > 外部HTMLvue
new Vue({内部无el项}).$mount('#app')是延迟加载,同下面的语句相同ajax
new Vue({el:"#app",***})算法
<div id="app"> <p>{{ message }}</p> <h1>{{message + '这是在outer HTML中的'}}</h1> </div>
var app = new Vue({ el: '#app', data: { message : "xuxiao is boy" }, template:"<h1>{{message +'这是在template中的'}}</h1>", // render: function(createElement) { // return createElement('h1', 'this is createElement') // } })
注意:这时候实例中的data选项尚未数据,因此在beforecreated中没法访问到data中的数据
注意:在beforecreated中千万不要去修改data中赋值的数据,最先也要在create里面去作(添加一些行为)
在模板渲染成HTML前调用,即一般初始化一些属性值,而后再渲染成视图, 未挂载DOM;created时还没完成挂载,没法经过id等得到DOM元素;vue-router
若在此阶段进行的 DOM 操做必定要放在 Vue.nextTick() 的回调函数中;由于created() 钩子函数执行的时候 DOM 其实并未进行任何渲染c#
Vue.nextTick( [callback, context] ):在下次 DOM 更新循环结束以后执行延迟回调。在修改数据以后当即使用这个方法,获取更新后的 DOM。
在created后,beforemount前,会检查el选项,没有就会调用vm.$mount(),而后就会继续检查template,没有的话就绑定el选项的html,进入beforemount后,编译模板为虚拟的DOM,,开始render,将虚拟DOM渲染到页面上;后端
从created到beforeMount的过程当中,数组
var app = new Vue({ el: '#app', data: { message : "xuxiao is boy" }, template:"<h1>{{message +'这是在template中的'}}</h1>", // render: function(createElement) { // return createElement('h1', 'this is createElement') // },
首先会判断vue实例中有没有el选项,若是有的话则进行下面的编译,可是若是没有el选项,则中止生命周期,直到vue实例上调用vm.$mount(el)。缓存
若是有el,再判断是否有template参数,若是有,则把其看成模板编译成render函数,app
若是没有,则把外部的html做为模板编译。template中的模板优先级高于outer HTML模板。
这是把outerHTML看成模板编译了
<div id="app">
<p>{{ message }}</p> <h1>{{message + '这是在outer HTML中的'}}</h1>
</div>
若是把实例中render function选项的注释去掉,则直接用render function里的,获得网页以下
因此按优先级来讲 render function>template>outerHTML
————————————————
在vue对象中还有一个render函数,它是以createElement做为参数,而后作渲染操做,并且咱们能够直接嵌入JSX.
综合排名优先级:render函数选项 > template选项 > outer HTML.
在这个阶段,$el还只是咱们在HTML里面写的节点。$el属性已存在,是虚拟dom,只是数据未挂载到模板中;有了el,编译了template|/outerHTML 能找到对应的template,并编译成render函数
完成建立vm,
完成el的双向绑定,完成挂载dom和渲染,能够在这个阶段对挂载的DOM进行操做;
ref 可在这发起后端请求,拿回数据,配合路由钩子作一些事情; 可对DOM 进行操做
载入后html已经渲染(ajax请求能够放在这个函数中),把vue实例中的data里的message挂载到BOM节点中去
更新前状态(view层的数据变化前,不是data中的数据改变前),从新渲染以前触发,而后vue的虚拟dom机制会从新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比以后从新渲染
数据已经更改完成,dom也从新render完成【具体的能够用this.$el.innerHTML能够看出已经改变了】
完成虚拟DOM的从新渲染和打补丁; 组件DOM 已完成更新; 可执行依赖的dom 操做 注意:不要在此函数中操做数据,会陷入死循环的。
当这个钩子被调用时,组件 DOM 已经更新,因此你如今能够执行依赖于 DOM 的操做。然而在大多数状况下,你应该避免在此期间更改状态。若是要相应状态改变,一般最好使用计算属性或 watcher取而代之。
view层的数据更新后,data中的数据同beforeUpdate,都是更新完之后的。注意:会发现
beforeUpdate
和updated
钩子函数中的$el
同样,根据官方理解beforeUpdate
应该指向虚拟dom,因此才会同样,而dom中的真正内容不同,可是beforeMount
和mouted
钩子函数中为何又会有区别呢?感受是设计的不足之处。**_
keep-alive 组件被移除时使用
实例销毁以前调用。在这一步,实例仍然彻底可用。
说明:
beforeDestroy(){ console.group('beforeDestroy 销毁前状态==========>>'); console.log("%c%s", "color:red", "el : "+this.$el); //[object HTMLDivElement] console.log(this.$el); console.log("%c%s", "color:red", "data : "+this.$data); //[object Object] console.log("%c%s", "color:red", "message: "+this.message); //今天周二了!!! },
官方解释:Vue 实例销毁后调用。调用后,Vue 实例指示的全部东西都会解绑定,全部的事件监听器会被移除,全部的子实例也会被销毁。
说明:执行destroy方法后,对data的改变不会再触发周期函数,此时的vue实例已经解除了事件监听以及和dom的绑定,可是dom结构依然存在。
destroyed(){ console.group('destroyed 销毁完成状态==========>>'); console.log("%c%s", "color:red", "el : "+this.$el); //[object HTMLDivElement] console.log(this.$el); console.log("%c%s", "color:red", "data : "+this.$data); //[object Object] console.log("%c%s", "color:red", "message: "+this.message); //今天周二了!!! },
加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程
父beforeUpdate->父updated
销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
参考文章:
http://www.javashuo.com/article/p-qhbnffir-gw.html
http://www.javashuo.com/article/p-vbplkdch-hs.html
https://www.jianshu.com/p/7026b73bb626