首页 > 代码库 > 聊一聊Vue实例与生命周期运行机制

聊一聊Vue实例与生命周期运行机制

Vue的实例是Vue框架的入口,担任MVVM中的ViewModel角色,所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数可以实现组件数据管理和DOM渲染两大重要功能。例如,实例需要配置数据观测(data observer)、编译模版、挂载实例到 DOM ,然后在数据变化时更新 DOM 。在这个过程中,事件钩子可以辅助我们对整个实例生成、编译、挂载、销毁等过程进行js控制,给我们提供了执行自定义逻辑的机会。所以学习实例的生命周期,能帮助我们理解vue实例的运行机制,更好地利用钩子函数完成我们的业务代码。

生命周期概览

  技术分享

  

Vue提供的可以注册的钩子都在上图片的红色框标注。 它们分别是:

  • beforeCreate

在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。此时的数据观察和事件机制都未形成。

  • created

实例已经创建完成之后同步调用,此时实例已经结束解析选项。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调,此时this便指向vue实例。然而,挂载阶段还没开始,还没有开始DOM编译,$el 属性目前不可见。

  • beforeMount

在挂载开始之前被调用:相关的 render 函数首次被调用。

  • mounted

el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。

  • beforeUpdate

数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。

  • updated

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。

该钩子在服务器端渲染期间不被调用。

  • beforeDestroy

实例销毁之前调用。在这一步,实例仍然完全可用。

  • destroyed

Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。

接下来做一个例子,看一下所有的生命周期具体执行时序是怎么样的

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 5     <title>Vue实例与生命周期</title>
 6     <script type="text/javascript" src="https://unpkg.com/vue/dist/vue.js"></script>
 7 </head>
 8 <body>
 9 
10 <div id="app">
11     <p>{{ message }}</p>
12 </div>
13 
14 <script type="text/javascript">
15 
16     var app = new Vue({
17         el: #app,
18         data: {
19             message : "Vue实例与生命周期"
20         },
21         beforeCreate: function () {
22             console.group(beforeCreate 创建前状态===============》);
23             console.log("%c%s", "color:red" , "el     : " + this.$el); //undefined
24             console.log("%c%s", "color:red","data   : " + this.$data); //undefined
25             console.log("%c%s", "color:red","message: " + this.message)
26         },
27         created: function () {
28             console.group(created 创建完毕状态===============》);
29             console.log("%c%s", "color:red","el     : " + this.$el); //undefined
30             console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
31             console.log("%c%s", "color:red","message: " + this.message); //已被初始化
32         },
33         beforeMount: function () {
34             console.group(beforeMount 挂载前状态===============》);
35             console.log("%c%s", "color:red","el     : " + (this.$el)); //已被初始化
36             console.log(this.$el);
37             console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
38             console.log("%c%s", "color:red","message: " + this.message); //已被初始化
39         },
40         mounted: function () {
41             console.group(mounted 挂载结束状态===============》);
42             console.log("%c%s", "color:red","el     : " + this.$el); //已被初始化
43             console.log(this.$el);
44             console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
45             console.log("%c%s", "color:red","message: " + this.message); //已被初始化
46         },
47         beforeUpdate: function () {
48             console.group(beforeUpdate 更新前状态===============》);
49             console.log("%c%s", "color:red","el     : " + this.$el);
50             console.log(this.$el);
51             console.log("%c%s", "color:red","data   : " + this.$data);
52             console.log("%c%s", "color:red","message: " + this.message);
53         },
54         updated: function () {
55             console.group(updated 更新完成状态===============》);
56             console.log("%c%s", "color:red","el     : " + this.$el);
57             console.log(this.$el);
58             console.log("%c%s", "color:red","data   : " + this.$data);
59             console.log("%c%s", "color:red","message: " + this.message);
60         },
61         beforeDestroy: function () {
62             console.group(beforeDestroy 销毁前状态===============》);
63             console.log("%c%s", "color:red","el     : " + this.$el);
64             console.log(this.$el);
65             console.log("%c%s", "color:red","data   : " + this.$data);
66             console.log("%c%s", "color:red","message: " + this.message);
67         },
68         destroyed: function () {
69             console.group(destroyed 销毁完成状态===============》);
70             console.log("%c%s", "color:red","el     : " + this.$el);
71             console.log(this.$el);
72             console.log("%c%s", "color:red","data   : " + this.$data);
73             console.log("%c%s", "color:red","message: " + this.message)
74         }
75     })
76 </script>
77 </body>
78 </html>

运行代码,在chrome console查看构造信息

技术分享

在console里面执行一下更新操作,data的值被修改后将会触发update操作。

  技术分享

执行实例销毁,将会触发destroy动作。如果后续依然想对实例进行其他操作,将会发现实例已经被销毁,操作不会成功。

  技术分享

从上面的代码和生命周期图解可以看到,Vue的实例封装很符合开发者的思维规范,生命周期非常清晰,是一款相当相当简洁强大优雅的框架,很值得我们研究学习使用。

好了,vue的生命周期就介绍到这儿,欢迎大家留言交流;喜欢或有帮助到您的话,点个赞或推荐支持一下,谢谢!

聊一聊Vue实例与生命周期运行机制