vue生命周期——超详细

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/TalonZhang/article/details/84111607

每个 Vue 实例创建时,都会经历一系列的初始化过程,同时也会调用相应的生命周期钩子。

生命周期

关于 Vue 生命周期,先放一张官方文档的图

在这个图中我们可以清楚地看到 Vue 的整个生命周期和它所提供的钩子函数。

钩子函数

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • update
  • beforeDestroy
  • destroyed

首先先运行一下下列代码,看看会发生什么,然后再慢慢分析。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue生命周期</title>
</head>
<body>
    <div id="app">
        <h1>{{message}}</h1>
    </div>

    <script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'Vue生命周期'
            },
            beforeCreate: function () {
                console.group('-----beforeCreate-----');
                console.log("%c%s", "color:red", "el      :" + this.$el);
                console.log("%c%s", "color:red", "data    :" + this.$data);
                console.log("%c%s", "color:red", "message :" + this.message);
            },
            created: function () {
                console.group('-----created-----');
                console.log("%c%s", "color:red", "el:     :" + this.$el);
                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>

代码运行结果如下:

由此我们可以看到,在 Vue 创建实例的过程中,调用了几个生命周期钩子。

1. beforeCreate 和 created 钩子函数之间的生命周期。

在这个生命周期之间,进行初始化事件,进行数据的观测,可以看到在 created 的时候数据已经和 data 属性进行绑定。但此时尚未挂载,el 还不可用。

2. created 和 beforeMount 之间的生命周期


如图,在这一阶段,首先会判断对象是否有 el 选项(option)。如果有的话就继续向下编译;如果没有则停止编译,也就意味着停止了生命周期,直到在该 Vue 实例上调用 vm.$mount(el)。

做个试验来看一下,在上面的示例代码中将 el 属性注释掉,则运行结果:

可以看到,当没有 el 选项时,代码运行到 created 的时候就停止了。

从图中可以看出,当判断有 el 选项时,代码会继续向下执行,接下来会判断是否有 template 选项。同样从图中可以看出:

  1. 如果 Vue 实例对象中有 template 选项,则将其作为模板编译成 render 函数。
  2. 如果没有 template 选项,则将外部 HTML(outerHTML)作为模板编译。
  3. 由此可以看出,template 中的模板优先级要高于 outerHTML 的优先级。

我们也可以做个实验来验证一下。运行下面的代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>vue生命周期学习</title>
</head>
<body>
  <div id="app">
    <!--html中修改的-->
    <h1>{{message + '---这是在outer HTML中的'}}</h1>
  </div>
</body>
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
<script>
  var vm = new Vue({
    el: '#app',
    template: "<h1>{{message +'---这是在template中的'}}</h1>", //在vue配置项中修改的
    data: {
      message: 'Vue的生命周期'
    }
});
</script>
</html>

执行后的结果为:

如果将 Vue 对象中的 template 属性注释掉则结果为:

结果跟我们从图中得出的结论的是一样的。

在 vue 对象中还有一个 render 函数,它是以 createElement 作为参数,然后做渲染操作。

new Vue({
	el: "#app",
	render: function (createElement) {
		return createElement('h1', 'This is createElement.'); 
	}
})

页面中渲染的是:

所以综合排名优先级:
render 函数选项 > template 选项 > outerHTML

3. beforeMount 和 mounted 之间的生命周期。


可以看到此时是给 vue 实例对象添加 $el 成员,并且替换掉挂载的 DOM 元素。在之前的结果图中可以看到 beforeMount 之前 el 还是 undefined。

4. mounted

注意看之前代码生成的结果图:

从图中我们可以清楚地看到,在 mounted 之前,h1 中还是通过 {{message}} 来占位的,因为此时还没有被挂到页面上,还是 JavaScript 中的虚拟 DOM 形式存在的。在 mounted 之后才发生了变化。

5. beforeUpdate 和 updated 之间的生命周期


从图中我们可以看到,当 vue 中的数据发生改变,会触发对应组件的重新渲染(re-render),先后调用 beforeUpdate 和 updated 钩子函数。
继续做实验,我们在控制台中输入:

vm.message = '触发组件更新'

控制台输出为:

我们可以看到触发了这两个钩子函数。
这里需要注意的一点是,两个函数中的 data 都已经更新为 “触发组件更新”,那区别是什么呢?

注意:

这里的 update 指的是,view 层的 update,而不是 vue 对象中 data 属性的 update。所以,这两个函数都发生在 data 改变之后(很容易理解,因为就是 data 属性的改变才触发了这两个函数),区别是 beforeUpdate 发生在 view 层的改变之前,也就是页面还没有重新渲染,此时页面仍然显示 “Vue的生命周期”(beforeUpdate 也是在页面重新渲染前修改 data 的最后时机);而 updated 是发生在 view 层改变之后,也就是此时的页面已经重新渲染为 “触发组件更新”。

6. beforeDestroy 和 destroyed 之间的生命周期


beforeDestroy 是在实例被销毁之前调用,在这一步,实例仍然完全可以调用
destroyed 函数在实例被销毁之后调用,此时 vue 实例指示的所有东西都会解绑,所有的事件监听器会被移除,所有的子实例也会被销毁

展开阅读全文

没有更多推荐了,返回首页