生命周期这个词大家一定非常熟悉,不同的对象有不同的生命周期,今天我想聊一聊Vue实例的生命周期,可能有人会说,我不了解生命周期不还是一样干活吗。对,你说的没错,但不可否认如果了解生命周期的话,可以帮助我们更好的对代码进行把控,比如我想在页面渲染完立即执行些操作,那你知道该定义在哪个钩子函数中吗?
一、生命周期的作用
每个Vue实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到DOM并在数据变化时更新DOM等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
以上是官方给出的解释,其实已经说的很明白了,就是能让我们对自己代码更好的把控,所谓的生命周期钩子就是生命周期事件的别名而已。
二、什么是生命周期
其实官方在生命周期的作用中也已经说了,简单的归纳一下加上我的理解就是,从Vue实例创建、运行到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期。
三、生命周期分哪些阶段(生命周期函数分类)
其实主要的生命周期一共就分为3个阶段,即创建期间,运行期间、销毁期间,只不过呢,在这些期间还有一些对应的生命周期函数,而我们要聊的也正是这些个生命周期函数,为了方便说明,先来一张生命周期图。
- beforeCreate
咱们由上到下依次说明,new Vue() 就不解释了,图示上已经说明了,表示开始创建一个Vue的实例对象,之后开始初始化一些生命周期和事件,但是要注意,此时只是初始化了一个空的Vue实例对象,这时候这个对象身上只有默认的一些生命周期函数和默认事件,其它的东西并没有创建出来,紧接着就会执行beforeCreate()这个钩子函数,但是在这个钩子函数执行的时候,data和methods中的数据却还没有被初始化。
<div id="app">{{msg}}</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'HelloVue'
},
methods: {
test() {
console.log('test'); // this.test is not a function
}
},
beforeCreate() {
console.log(this.msg); // undefined
this.test();
}
});
</script>
- created
继续初始化直至实例已经创建完成,并立即调用此钩子函数,在created中,因为data和methods都已经被初始化完毕,所以,要想操作data中的数据或调用methods中的方法,只能在此钩子函数中或者之后进行。
<div id="app">{{msg}}</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'HelloVue'
},
methods: {
test() {
console.log('test'); // test
}
},
beforeCreate() {
// console.log(this.msg);
// this.test();
},
created() {
console.log(this.msg); // HelloVue
this.test();
}
});
</script>
- beforeMount
接下来进入模板编译阶段,Vue开始编译模板,并在内存中生成一个编译好的最终模板字符串,然后把这个模板字符串渲染为内存中的DOM,但是要注意的是,此时只是在内存中渲染好了模板,还并没有把模板挂载到真正的页面中去,而此函数也正是在编译好模板后,但是却未正式挂载到页面上时被调用的。
<div id="app">{{msg}}</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'HelloVue'
},
methods: {
test() {
// console.log('test');
}
},
beforeCreate() {
// console.log(this.msg);
// this.test();
},
created() {
// console.log(this.msg);
// this.test();
},
beforeMount() {
console.log(document.getElementById('app').innerText); // {{msg}}
}
});
</script>
- mounted
然后会将内存中编译好的模板,挂载到真正的浏览器的页面中去,只要执行完了mounted钩子函数,就可以认为已经彻底完成了挂载,用户已经可以看到渲染好的页面,开始进入运行阶段了,由此可知,如果想要操作页面上的DOM节点,那一定不能早于此钩子函数。
<div id="app">{{msg}}</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'HelloVue'
},
methods: {
test() {
// console.log('test');
}
},
beforeCreate() {
// console.log(this.msg);
// this.test();
},
created() {
// console.log(this.msg);
// this.test();
},
beforeMount() {
// console.log(document.getElementById('app').innerText);
},
mounted() {
console.log(document.getElementById('app').innerText); // HelloVue
}
});
</script>
- beforeUpdate
此时已经是属于运行阶段了,运行阶段的钩子函数的触发取决于data数据的改变,如果没改变将不会触发,如果改变多次那就会被触发多次,当数据被修改的时候,会先触发beforeUpdate这个钩子函数,但是此时数据虽然是更新了,可是却还并未同步到页面中,因此页面中的数据此时还是显示的是旧的数据。
<div id="app">
<input type="text" v-model="msg" />
<p id="p">{{ msg }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'HelloVue'
},
methods: {
test() {
// console.log('test');
}
},
beforeCreate() {
// console.log(this.msg);
// this.test();
},
created() {
// console.log(this.msg);
// this.test();
},
beforeMount() {
// console.log(document.getElementById('app').innerText);
},
mounted() {
// console.log(document.getElementById('app').innerText);
},
beforeUpdate() {
console.log('实际数据:' + this.msg); // 实际数据:Hello
console.log('界面显示:' + document.getElementById('p').innerText); // 界面显示:HelloVue
}
});
</script>
- updated
然后根据data中的最新数据,重新渲染虚拟DOM,并应用更新,再把最新的虚拟DOM重新渲染到到真实的页面中去,这时候就完成了数据的更新,之后调用updated钩子函数,你会发现页面和data数据已经保持同步了,都是最新的。
<div id="app">
<input type="text" v-model="msg" />
<p id="p">{{ msg }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'HelloVue'
},
methods: {
test() {
// console.log('test');
}
},
beforeCreate() {
// console.log(this.msg);
// this.test();
},
created() {
// console.log(this.msg);
// this.test();
},
beforeMount() {
// console.log(document.getElementById('app').innerText);
},
mounted() {
// console.log(document.getElementById('app').innerText);
},
beforeUpdate() {
// console.log('实际数据:' + this.msg);
// console.log('界面显示:' + document.getElementById('p').innerText);
},
updated() {
console.log('实际数据:' + this.msg); // 实际数据:Hello
console.log('界面显示:' + document.getElementById('p').innerText); // 界面显示:Hello
}
});
</script>
- beforeDestroy
运行阶段过后,执行beforeDestroy钩子函数的时候,Vue实例就已经从运行阶段进入到了销毁阶段,但此时实例身上的东西还处于可用状态,因为还没有真正执行销毁过程。
- destroyed
接着开始解除绑定,销毁子组件以及事件监听器等。当执行到destroyed函数的时候,因为组件已经完全销毁了,所以此时所有东西都已经不可用了。
你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。