Vue生命周期

Vue生命周期流程图

官方原图

vue生命周期流程图

自己对照的简单翻译了一下

vue生命周期流程图

生命周期的解析和应用

Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。通俗说就是 Vue 实例从创建到销毁的过程,就是生命周期。

生命周期的解析

生命周期钩子解析
beforeCreate在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount在挂载开始之前被调用:相关的 render 函数首次被调用。
mountedel 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
beforeUpdate数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
updated由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。
activatedkeep-alive 组件激活时调用。
deactivatedkeep-alive 组件停用时调用。
beforeDestroy实例销毁之前调用。在这一步,实例仍然完全可用。
destroyedVue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

生命周期的应用

  1. beforecreate:完成实例初始化,初始化非响应式变量,this指向创建的实例,可以在这加个loading事件,datacomputedwatchmethods上的方法和数据均不能访问。
  2. created: 实例创建完成,完成数据(datapropscomputed)的初始化 导入依赖项,可访问datacomputedwatchmethods上的方法和数据,未挂载 DOM,不能访问$el$ref为空数组。可在这结束loading,还做一些初始化,实现函数自执行, 可以对data数据进行操作,可进行一些请求,请求不易过多,避免白屏时间太长。若在此阶段进行的 DOM 操作一定要放在 Vue.nextTick() 的回调函数中。
  3. berofeMount:有了 el,编译了template或者outerHTML,能找到对应的template,并编译成render函数。
  4. mounted:完成创建vm.$el和双向绑定,完成挂载 DOM 和渲染;可访问DOM节点和$ref,可在这发起后端请求,拿回数据,配合路由钩子做一些事情;可对DOM 进行操作。
  5. beforeUpdate:数据更新之前可在更新前访问现有的DOM,如手动移除添加的事件监听器;
  6. updated :完成虚拟DOM的重新渲染和打补丁;组件DOM 已完成更新;可执行依赖的DOM操作。注意:不要在此函数中操作数据,会陷入死循环的。
  7. activated:在使用vue-router时有时需要使用<keep-alive></keep-alive>来缓存组件状态,这个时候created钩子就不会被重复调用了,如果我们的子组件需要在每次加载的时候进行某些操作,可以使用activated钩子触发。
  8. deactivated:keep-alive 组件被移除时使用。
  9. beforeDestroy:在执行app.$destroy()之前可做一些删除提示,如:你确认删除XX吗? 可用于销毁定时器,解绑全局时间 销毁插件对象。
  10. destroyed:当前组件已被删除,销毁监听事件,组件,子实例也被销毁。这时组件已经没有了,你无法操作里面的任何东西了。

测试DEMO

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>
<body>

<div id="app">
     <p>{{ message }}</p>
</div>

<script type="text/javascript">
    
  var app = new Vue({
      el: '#app',
      data: {
          message : "Hello World!" 
      },
       beforeCreate: function () {
                console.group('beforeCreate 创建前状态===============》');
               console.log("%c%s", "color:red" , "el     : " + this.$el); //undefined
               console.log("%c%s", "color:red","data   : " + this.$data); //undefined 
               console.log("%c%s", "color:red","message: " + this.message)  
        },
        created: function () {
            console.group('created 创建完毕状态===============》');
            console.log("%c%s", "color:red","el     : " + this.$el); //undefined
               console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化 
               console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
        beforeMount: function () {
            console.group('beforeMount 挂载前状态===============》');
            console.log("%c%s", "color:red","el     : " + (this.$el)); //已被初始化
            console.log(this.$el);
               console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化  
               console.log("%c%s", "color:red","message: " + this.message); //已被初始化  
        },
        mounted: function () {
            console.group('mounted 挂载结束状态===============》');
            console.log("%c%s", "color:red","el     : " + this.$el); //已被初始化
            console.log(this.$el);    
               console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
               console.log("%c%s", "color:red","message: " + this.message); //已被初始化 
        },
        beforeUpdate: function () {
            console.group('beforeUpdate 更新前状态===============》');
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);   
               console.log("%c%s", "color:red","data   : " + this.$data); 
               console.log("%c%s", "color:red","message: " + this.message); 
        },
        updated: function () {
            console.group('updated 更新完成状态===============》');
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el); 
               console.log("%c%s", "color:red","data   : " + this.$data); 
               console.log("%c%s", "color:red","message: " + this.message); 
        },
        beforeDestroy: function () {
            console.group('beforeDestroy 销毁前状态===============》');
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);    
               console.log("%c%s", "color:red","data   : " + this.$data); 
               console.log("%c%s", "color:red","message: " + this.message); 
        },
        destroyed: function () {
            console.group('destroyed 销毁完成状态===============》');
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);  
               console.log("%c%s", "color:red","data   : " + this.$data); 
               console.log("%c%s", "color:red","message: " + this.message)
        }
    })
</script>
</body>
</html>

打开F12可以查看生命周期各个时期的钩子函数的状态:

20180609162142.png

由上图知:

  1. beforeCrete: 此时$eldata都为undefined,没有初始化。
  2. created: 创建后data初始化了,而$el没有。
  3. brforeMount: 挂在之前,$eldata都初始化了。
  4. mounted: Vue实例挂载完成了。

注意: beforeMount里是{{message}},mounted里是Hello World,说明挂载前$el的值为'虚拟'的元素节点,挂载后'虚拟'的Dom节点被真实的Dom节点替换。

在控制台里输入app.message = '数据更新'

20180609162629.png

由此可见,当data数据变化时只会触发update。

在控制台里输入app.$destroy(),然后再输入app.message = '数据销毁',数据已经不会再有变化。

20180609162933.png

执行完destroy操作后,data里的数据没有变化,但是Dom结构还存在,也就是Vue实例不再受控制了,完成了解耦。

添加新评论