闵超的主页

Vue生命周期详述

2018-07-12
闵超
Vue

Vue生命周期详述

每次面试都会被问到vue是否熟悉,回答得都不够具体,其实vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。

详解生命周期——图解

vue生命周期中文注解.png

Vue 1.0+ Vue 2.0+ 描述
init beforeCreate 组件实例刚被创建,组件属性计算之前,如data等
created created 组件实例创建完成,属性已绑定,但DOM还没生成,$el还不存在
beforeCompile beforeMount 模板编译/挂载之前
compiled mounted 模板编译/挂载之后
ready mounted 模板编译/挂载之后(不保证组件已在document中)
- beforeUpdate 组件更新之前
- updated 组件更新之后
- activated for keep-alive,组件被激活时调用
- deactivated for keep-alive,组件被移除时调用
attached - (废弃) 附属时调用
detached - (废弃) 分离时调用
beforeDestory beforeDestory 组件销毁之前调用
destoryed destoryed 组件销毁后调用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue入门之 生命周期详解</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        
    </div>

<script type="text/javascript">
    console.log("--------------第一阶段-----创建和挂载---------------------");
    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) //undefined 
        },
        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)
        }
    });
    setTimeout(function(){
        console.log("--------------第二阶段-----更新--------------------------");
        app.message = "updated message";
    },1000);
    setTimeout(function(){
         console.log("--------------第三阶段-----销毁--------------------------");
        app.$destroy();
    },2000);
   
</script>
</body>
</html> 

阶段分析

在chrome浏览器里打开,F12看console查看,分三个阶段解读:

阶段一:创建和挂载

  • beforecreated:el 和 data 并未初始化
  • created:完成了 data 数据的初始化,el没有
  • beforeMount:完成了 el 和 data 初始化
  • mounted :完成挂载

阶段二:更新

  • beforeUpdate:虚拟DOM中根据data变化去更新html
  • updated:将虚拟DOM更新完成的HTML更新到页面中

阶段三:销毁

  • beforeDestroy:销毁之前调用

  • destroyed:销毁之后调用,之后再执行app.message= ‘hello vue’,页面不会同步更新。

图解分析

vue生命周期截图.png

create 和 mounted 相关

另外在created到beforeMount挂载,我们能发现el还是 ,这里就是应用的 Virtual DOM(虚拟Dom)技术,先把坑占住了。到后面mounted挂载的时候再把值渲染进去。

destroy 相关

有关于销毁,暂时还不是很清楚。我们在console里执行下命令对 vue实例进行销毁。销毁完成后,我们再重新改变message的值,vue不再对此动作进行响应了。但是原先生成的dom元素还存在,可以这么理解,执行了destroy操作,后续就不再受vue控制了。

生命周期总结

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

每一个组件或者实例都会经历一个完整的生命周期,总共分为三个阶段:初始化(创建和挂载)、运行中(更新)、销毁。

  1. 实例、组件通过new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate钩子函数,这个时候,数据还没有挂载呢,只是一个空壳,无法访问到数据和真实的dom,一般不做操作

  2. 挂载数据,绑定事件等等,然后执行created函数,这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发updated函数,在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取

  3. 接下来开始找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染,然后执行beforeMount钩子函数,在这个函数中虚拟dom已经创建完成,马上就要渲染,在这里也可以更改数据,不会触发updated,在这里可以在渲染前最后一次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取

  4. 接下来开始render,渲染出真实dom,然后执行mounted钩子函数,此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,可以在这里操作真实dom等事情…

  5. 当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染,一般不做什么事儿

  6. 当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom

  7. 当经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等

  8. 组件的数据绑定、监听…去掉后只剩下dom空壳,这个时候,执行destroyed,在这里做善后工作也可以


Content

如果喜欢,打个赏,加个好友吧

扫描二维码打赏

扫描二维码打赏