Vue中生命周期的理解

vue生命周期

生命周期能够分为四个阶段,初始化阶段,模板编译阶段,挂载阶段,已挂载和卸载阶段。html

  •   el :选择器
  •   $el:对应选择器的template模板(html代码)
  •   render:也是vue实例中的一项,其参数更接近vue解析器,按优先级,render参数 > vue实例对象中有template > 外部的HTML模板 后面两个也是将其编译成render函数;【注意】render选项参数比template更接近Vue解析器!因此优先级以下:

     render函数选项  > template参数  > 外部HTMLvue

  •   $mount :当Vue实例没有el属性时,则该实例尚没有挂载到某个dom中,假如须要延迟挂载,能够在以后手动调用vm.$mount()方法来挂载。例如:

         new Vue({内部无el项}).$mount('#app')是延迟加载,同下面的语句相同ajax

         new Vue({el:"#app",***})算法

  1. computed计算属性可用于快速计算视图(View)中显示的属性。这些计算将被缓存,而且只在须要时更新.
  2. watch主要用于监控vue实例的变化,它监控的变量固然必须在data里面声明才能够,它能够监控一个变量,也能够是一个对象,通常用于监控路由、input输入框的值特殊处理等等,它比较适合的场景是一个数据影响多个数据.
  3. methods每当触发从新渲染时,方法的调用方式将老是再次执行函数。所以,函数必须是一个纯函数。它不能有反作用。输出只能依赖于传递给函数的值。

HTML

<div id="app">
    <p>{{ message }}</p>
    <h1>{{message + '这是在outer HTML中的'}}</h1>
</div>

js

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')
    // }
})

最终结果

20190520142852951.png
20190520142920131.png
20190520142946922.png

vue整个过程作了些什么

new Vue()建立实例

  1. vue项目都是经过组件化进行实现的,一个页面经过若干组件组成,构成一个组件树,
  2. 每个组件都经过一个vue实例来进行管理,
  3. 每当要渲染一个组件前,都会为该组件建立一个vue实例来管理组件中的数据和事件方法。
  4. 经过new Vue()建立实例时,实际建立了一个vue实例的空壳,初始化生命周期和事件
注意:这时候实例中的data选项尚未数据,因此在beforecreated中没法访问到data中的数据

初始化阶段

beforecreate

  1. 在这个阶段,完成实例初始化,
  2. 初始化非响应式变量 this指向建立的实例;
  3. 能够在这加个loading事件;
  4. data computed watch methods上的方法和数据均不能访问,这个时候的Vue实例还什么都没有,
  5. $route对象是存在的,能够根据路由信息进行重定向之类的操做;
  6. 这个阶段的data对象未完成初始化,el也没有完成初始化;
  7. DOM尚未开始
注意:在beforecreated中千万不要去修改data中赋值的数据,最先也要在create里面去作(添加一些行为)

created 【建立完成】

在模板渲染成HTML前调用,即一般初始化一些属性值,而后再渲染成视图, 未挂载DOM;created时还没完成挂载,没法经过id等得到DOM元素;vue-router

  1. 实例建立完成 完成数据(data props computed)的初始化 导入依赖项。
  2. 可访问data computed watch methods上的方法和数据 ;
  3. 不能访问el【初始化还未完成】,ref为空数组 ;不能对元素进行操做;
  4. 可在这结束loading,
  5. 还作一些初始化,实现函数自执行,
  6. 能够对data数据进行操做,可进行一些请求,请求不易过多,避免白屏时间太长。
  7. el仍是undefined,
  8. 而数据已经与data中的属性进行绑定(放在data中属性当值发生改变的同时,视图也会发生变化),
  9. 在这里能够在渲染前倒数第二次更改数据的机会,不会触发其余的钩子函数,通常能够在这里作初始数据的获取
  10. 若在此阶段进行的 DOM 操做必定要放在 Vue.nextTick() 的回调函数中;由于created() 钩子函数执行的时候 DOM 其实并未进行任何渲染c#

    Vue.nextTick( [callback, context] ):在下次 DOM 更新循环结束以后执行延迟回调。在修改数据以后当即使用这个方法,获取更新后的 DOM。

模板编译阶段

beforemount & mount

在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函数,
20190520143735512.pngapp

若是没有,则把外部的html做为模板编译。template中的模板优先级高于outer HTML模板。

20190520143925157.png
这是把outerHTML看成模板编译了

<div id="app">

<p>{{ message }}</p>
<h1>{{message + '这是在outer HTML中的'}}</h1>

</div>

若是把实例中render function选项的注释去掉,则直接用render function里的,获得网页以下

2019052014420087.png

因此按优先级来讲 render function>template>outerHTML
————————————————

在vue对象中还有一个render函数,它是以createElement做为参数,而后作渲染操做,并且咱们能够直接嵌入JSX.
综合排名优先级:render函数选项 > template选项 > outer HTML.

挂载阶段

beforeMount【挂载以前】

在这个阶段,$el还只是咱们在HTML里面写的节点。$el属性已存在,是虚拟dom,只是数据未挂载到模板中;有了el,编译了template|/outerHTML 能找到对应的template,并编译成render函数

  1. 载入前(完成了data和el数据初始化),
  2. 可是页面中的内容仍是vue中的占位符
  3. $el属性已存在,是虚拟dom,只是数据未挂载到模板中。
  4. data中的message信息没有被挂在到Bom节点中,
  5. 在这里能够在渲染前最后一次更改数据的机会,不会触发其余的钩子函数,通常能够在这里作初始数据的获取

mounted 【成功挂载】

完成建立vm,

完成el的双向绑定,完成挂载dom和渲染,能够在这个阶段对挂载的DOM进行操做;

ref 可在这发起后端请求,拿回数据,配合路由钩子作一些事情; 可对DOM 进行操做

载入后html已经渲染(ajax请求能够放在这个函数中),把vue实例中的data里的message挂载到BOM节点中去

beforeUpdate

更新前状态(view层的数据变化前,不是data中的数据改变前),从新渲染以前触发,而后vue的虚拟dom机制会从新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比以后从新渲染

  • 只有view上面的数据变化才会触发beforeUpdate和updated,仅属于data中的数据改变是并不能触发;
  • 数据更新以前 可在更新前访问现有的DOM,如手动移除添加的事件监听器;
  • beforeUpdate是指view层的数据变化前【具体的能够用this.$el.innerHTML能够看出没有改变】,不是data中的数据改变前触发。由于Vue是数据驱动的

updated

数据已经更改完成,dom也从新render完成【具体的能够用this.$el.innerHTML能够看出已经改变了

完成虚拟DOM的从新渲染和打补丁; 组件DOM 已完成更新; 可执行依赖的dom 操做 注意:不要在此函数中操做数据,会陷入死循环的。

当这个钩子被调用时,组件 DOM 已经更新,因此你如今能够执行依赖于 DOM 的操做。然而在大多数状况下,你应该避免在此期间更改状态。若是要相应状态改变,一般最好使用计算属性或 watcher取而代之。

view层的数据更新后,data中的数据同beforeUpdate,都是更新完之后的。

注意:会发现beforeUpdateupdated钩子函数中的$el同样,根据官方理解beforeUpdate应该指向虚拟dom,因此才会同样,而dom中的真正内容不同,可是beforeMountmouted钩子函数中为何又会有区别呢?感受是设计的不足之处。**_

activated

  • 在使用vue-router时有时须要使用来缓存组件状态,这个时候created钩子就不会被重复调用了,
  • 若是咱们的子组件须要在每次加载的时候进行某些操做,可使用activated钩子触发

deactivated

keep-alive 组件被移除时使用

beforeDestroy

实例销毁以前调用。在这一步,实例仍然彻底可用。
说明:

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);   //今天周二了!!!
},

destroyed

官方解释: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:这个时候data,watcher,methods通通没有,这个时候的Vue实例还什么都没有,可是$route对象是存在的,能够根据路由信息进行重定向之类的操做。
  • 20190520144436609.png
  • 20190520144455848.png

mouted和created

20190520144542445.png

父子组件嵌套时触发钩子函数顺序

加载渲染过程

  父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

子组件更新过程
  父beforeUpdate->子beforeUpdate->子updated->父updated

父组件更新过程
  父beforeUpdate->父updated

销毁过程
  父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

总结

  • beforecreate:能够在这加个loading事件
  • created :在这结束loading,还作一些初始化,实现函数自执行
  • mounted : 在这发起后端请求,拿回数据,配合路由钩子作一些事情
  • beforeDestory: 你确认删除vue实例了吗?
  • destoryed :当前实例已被销毁,解绑相关指令和事件监听器

参考文章:
http://www.javashuo.com/article/p-qhbnffir-gw.html
http://www.javashuo.com/article/p-vbplkdch-hs.html
https://www.jianshu.com/p/7026b73bb626

相关文章
相关标签/搜索