每个vue实例被创建时都会经历一系列初始化过程,例如:设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这些过程中会运行一些vue生命周期中的钩子函数,这些函数为用户提供在创建vue实例及创建完成后期不同阶段添加自己代码的机会。
钩子函数中的this指向当前vue实例。
vue实例生成及后期的钩子函数如下:
- beforeCreate created
- beforeMount mounted
- beforeUpdate updated
- beforeDestroy destroyed
注意: beforeCreate、created、beforeMount、mounted是在初始化实例时执行,会默认按照先后顺序执行。但是当更新数据时,就不再执行这4个钩子函数。
vue生命周期图示
Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
每一个组件或者实例都会经历一个完整的生命周期,总共分为三个阶段:初始化、运行中、销毁。
-
1、实例、组件通过new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate钩子函数,这个时候,数据还没有挂载,只是一个空壳,无法访问到数据和真实的dom,一般不做操作
-
2、挂载数据,绑定事件等等,然后执行created函数,这个时候已经可以使用data中的数据,也可以更改数据,在这里更改数据不会触发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,在这里做善后工作也可以
<div id="app">
<ul>
<li v-for="a in arr">{{a}}</li>
</ul>
{{msg}}
<button @click="fn">改变</button>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el:"#app",//它是选择器
data:{//data的值可以是对象或是函数,函数必须返回对象
msg:"hello",
arr:[1,2,3]
},
methods:{
fn(){
this.msg = "world";
}
},
beforeCreate(){
// 在这个钩子函数执行之前初始化一些事件和vue的生命周期
// 在该函数执行时不能获取data中的数据,不能操作真实DOM
console.log(this.msg);//undefined
console.log(document.getElementsByTagName("li"));//只能获取页面上的一个li并且行间还有vue指令
console.log("beforeCreate");
},
created(){
// 在执行这个钩子函数之前初始化注入和响应数据。一般在该函数中用于获取初始化数据
// 在该函数执行时可以获取data中的数据,但是不能操作真实DOM
// 在该函数中可以修改数据,此时数据还没有挂载到真实dom上,不会触发update函数
console.log(this.msg);//"hello"
console.log(document.getElementsByTagName("li"));//只能获取页面上的一个li并且行间还有vue指令
console.log("created");
},
beforeMount(){
// 在这个钩子函数之前判断是否有el、模板
// 在该函数执行时可以获取data中的数据,但是不能操作真实DOM
// 这是最后一次可以修改数据的地方,此时数据还没有挂载到真实dom上
console.log(this.msg);//"hello"
console.log(document.getElementsByTagName("li"));//只能获取页面上的一个li并且行间还有vue指令
console.log("beforeMount");
},
mounted(){
// 在该函数执行前把vue实例虚拟的dom挂载到真实dom上
// 在该函数执行时可以获取data中的数据,也能操作真实DOM
console.log(this.msg);//"hello"
console.log(document.getElementsByTagName("li"));//获取到页面上的3个li
console.log("mounted");
},
beforeUpdate(){
console.log("beforeUpdate");
},
updated(){
// 在该函数之前通过dom-diff算法进行dom对比,并重新渲染和打补丁
console.log("updated");
},
beforeDestroy(){
// vue实例不会自动销毁
console.log("beforeDestroy");
},
destroyed(){
// 销毁以后vue实例对象存在,但是会销毁观察者、子组件、事件监听者
console.log("destroyed");
}
});
vm.$destroy();//销毁vm实例
vm.msg = "123";
console.log(vm.msg);//"123"
</script>
注意: 虽然销毁了vue实例,但是vue对象依然存在,可以修改vue对象中的数据,只是不再更新对应的视图。