Vue.js-07:第七章 - Vue 实例的生命周期
一、前言
在之前的 vue 学习中,我们在使用 vue 时,都会创建一个 vue 的实例,而每个 vue 实例在被创建时都要经过一系列的初始化过程。例如,需要设置数据监听、编译模板、将实例挂载到 dom 并在数据变化时更新 dom 等。在这个过程中,vue 会运行一些生命周期钩子函数,而我们则可以在钩子函数中编写一些自定义方法,用以在 vue 的整个生命周期中某些阶段实现我们特殊需求。那么,本章,我们就来了解 vue 实例的生命周期钩子函数。
学习系列目录地址:
仓储地址:https://github.com/lanesra712/vuetrial/blob/master/chapter01-rookie/hocks.html
二、干货合集
在我们使用 vue 的时候,都会先创建一个 vue 实例,这个实例不仅是我们挂载 vue 框架的入口,也是 mvvm 思想中的 vm(viewmodel)。在我们使用 vue 的整个过程中,归根结底都是在对这个 vue 实例进行操作。因此,只有当我们了解 vue 实例的生命周期之后,才可以更好的实现我们的业务逻辑。
在 vue 官网的这张生命周期图示中,我们可以看到整个生命周期中包含了8个钩子函数:beforecreate、created、beforemount、mounted、beforeupdate、updated、beforedestroy、destroyed。从字面意思我们就可以清楚的看出来,这8个钩子函数两个一组,分别对应于 vue 实例的创建、挂载、更新、销毁,接下来,我们就根据这四个阶段,解释 vue 实例各个阶段中的钩子函数的作用。
1、beforecreate & created
在我们通过 new vue() 创建了一个 vue 实例之后,会执行 init 方法,此时只会初始化 vue 实例所包含的一些默认的事件与生命周期函数,在这个实例还未被完全创建之前,则会执行我们的 beforecreate 钩子函数。
在下面的例子中,我们在实例化 vue 对象时,自定义了一个 message 属性,同时设定了一个 show 方法,现在我们来看看当实例并没有完全被创建之前,是否能够获取到我们自定义的属性与方法。
<div id="app"> {{message}} </div> <script> var vm = new vue({ el: '#app', data: { message: 'hello world!' }, methods: { show() { console.log('执行了 show 方法'); } }, beforecreate() { console.log(`vue 实例挂载对象 el:${this.$el}`) console.log(`vue 实例的 data 对象:${this.$data}`) console.log(`vue 实例的 message 属性值:${this.message}`) console.log(`vue 实例的 methods 对象:${this.$options.methods}`) this.show(); } }) </script>
从浏览器的控制台中我们可以看到,此时,vue 实例中的 data、methods 对象,或是我们定义的 vue 实例的挂载点元素,在 beforecreated 生命周期钩子函数执行时,都没有进行了初始化。
当 beforecreated 钩子函数执行完成后,vue 实例已经初始化完成,此时将要执行生命周期中的 created 钩子函数来监听我们对于数据的更改或是监听事件。
<div id="app"> {{message}} </div> <script> var vm = new vue({ el: '#app', data: { message: 'hello world!' }, methods: { show() { console.log('执行了 show 方法'); } }, created() { console.log(`vue 实例挂载对象 el:${this.$el}`) console.log(`vue 实例的 data 对象:${this.$data}`) console.log(`vue 实例的 message 属性值:${this.message}`) console.log(`vue 实例的 methods 对象:${this.$options.methods}`) this.show(); } }) </script>
从浏览器控制台打印出的信息可以看出,在执行 created 钩子函数的过程中,对于自定义的属性 message、自定义的方法 show 已经初始化完成,此时,整个 vue 实例已经初始化完成。但是,对于我们的 vue 实例的挂载点元素还没有进行初始化。也就是说,当执行完 created 之后,vue 实例与 view(视图层)之间依旧是处于隔离的状态,初始化完成的 vue 实例也依旧没有与 dom 进行绑定。
2、beforemount & mounted
当 vue 实例执行完 beforecreated、created 钩子函数之后,vue 实例已经初始化完成,而 vue 实例并没有挂载到页面的 dom 上。在挂载到页面 dom 元素之前,则需要执行 beforemount 钩子函数将我们的实例绑定到模板上进行编译渲染。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new vue({ el: '#app', data: { message: 'hello world!' }, methods: { show() { console.log('执行了 show 方法'); } }, beforemount() { console.log(document.getelementbyid('h3').innertext) } }) </script>
从控制台输出的信息可以看到,当执行到 beforemount 钩子函数时,已经将模板编译完成,但是尚未挂载到页面上去。
当把编译完成的模板挂载到页面上时,则需要执行 mounted 钩子函数,在这个阶段,用户就可以看到已经渲染好的页面。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new vue({ el: '#app', data: { message: 'hello world!' }, methods: { show() { console.log('执行了 show 方法'); } }, mounted() { console.log(document.getelementbyid('h3').innertext) } }) </script>
这里我们可以看到,已经可以获取到差值表达式的值,即当执行到 mounted 钩子函数时,页面已经渲染完成了。
从上面的例子中可以看出,mounted 是创建 vue 实例过程中的最后一个生命周期钩子函数,当执行完 mounted 钩子函数之后,实例已经被完成创建好,并已经渲染到页面中,此时,如果我们不对实例进行任何的操作的话,vue 实例则不会执行 新的生命周期钩子函数。
3、beforeupdate & updated
在执行完了 mounted 钩子函数之后,vue 实例实际已经脱离了实例的创建阶段,进入实例的运行阶段。此时,当我们对实例的 data 进行修改时,则会触发 beforeupdate、updated 这两个钩子函数。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new vue({ el: '#app', data: { message: 'hello world!' }, methods: { show() { console.log('执行了 show 方法'); } }, beforeupdate() { console.log(`页面上的数据:${document.getelementbyid('h3').innertext}`) console.log(`data 中的 message 数据:${this.message}`) } }) </script>
我们可以看到,当我们对 data 中的 message 属性进行修改时,在执行 beforeupdate 钩子函数时,页面上的数据还是旧的数据,而 data 中 message 属性已经将值修改成了最新的值(这里页面上显示的为修改后的数据则是因为执行了后面的钩子函数,将修改后的数据同步渲染到了页面上)。
vue 作为一个具有数据双向绑定特性的框架,当我们实时修改了页面元素的值之后,肯定希望页面可以同步变更数据。而在执行 beforeupdate 钩子函数之后,我们已经在实例中修改了数据,现在只需要重新渲染到页面就可以了,这时候,则会执行 updated 钩子函数。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new vue({ el: '#app', data: { message: 'hello world!' }, methods: { show() { console.log('执行了 show 方法'); } }, updated() { console.log(`页面上的数据:${document.getelementbyid('h3').innertext}`) console.log(`data 中的 message 数据:${this.message}`) } }) </script>
从控制台可以看到,当 updated 钩子函数执行的时候,页面和 data 中的数据已经完成了同步,都显示的是最新的数据。此时,整个页面数据实时变更的操作也已经完成了。
4、beforedestroy & destroyed
既然有 vue 实例的创建,那么在我们不需要 vue 实例的时候就需要将这个实例进行销毁。而 beforedestroy 以及 destroyed 钩子函数则会帮我们实现这一目的。
<div id="app"> {{message}} </div> <script> var vm = new vue({ el: '#app', data: { message: 'hello world!' }, methods: { show() { console.log('执行了 show 方法'); } }, beforedestroy() { console.log(`vue 实例挂载对象 el:${this.$el}`) console.log(`vue 实例的 data 对象:${this.$data}`) console.log(`vue 实例的 message 属性值:${this.message}`) console.log(`vue 实例的 methods 对象:${this.$options.methods}`) this.show(); }, destroyed() { console.log(`vue 实例挂载对象 el:${this.$el}`) console.log(`vue 实例的 data 对象:${this.$data}`) console.log(`vue 实例的 message 属性值:${this.message}`) console.log(`vue 实例的 methods 对象:${this.$options.methods}`) this.show(); } }) </script>
这里,我们手动销毁 vue 实例,从控制台的输出内容可以看到,在 beforedestroy 和 destroyed 钩子函数执行中,我们依旧可以获取到 vue 实例的相关内容,可是,当我们选择更新 message 属性的值时会发现,此时,页面上显示的值并没有发生改变。原来,这里的销毁并不指代'抹去'这个 vue 实例,而是表示将 vue 实例与页面的 dom 元素进行'解绑'。
三、总结
钩子函数 | 描述 |
---|---|
beforecreate | vue 实例进行初始化,此时实例的各个组件还没有进行初始化完成,因此不能访问到 data、computed、watch、methods 上的方法和数据,同时,vue 实例的挂载点也没有进行初始化 |
created | vue 实例初始化完成,此时可以访问 data、computed、watch、methods 上的方法和数据,但是依旧没有进行 vue 实例的挂载点初始化 |
beforemount | 将实例绑定到模板并进行渲染,但并不会将实例挂载到页面上 |
mounted | 将渲染好的模板绑定到页面上,此时,vue 实例已完全创建好 |
beforeupdate | 数据变更时调用,在实例数据更改之前执行任何应该发生的自定义逻辑或操作 |
updated | 将 vue 实例更新完成的数据重新渲染到内存中的虚拟 dom 上,再将虚拟 dom 应用到页面上 |
beforedestroy | vue 实例进入销毁阶段,此时实例上的 data、methods、过滤器、指令等等还是处于可用的状态,还没有真正执行销毁的过程(解除与页面 dom 元素的绑定) |
destroyed | 实例被销毁(解除与页面 dom 元素的绑定) |
四、参考
1、
3、
4、