Vue 生命周期详解
一.概念
每个vue实例或组件(组件本质上就是一个具有预定义选项的实例)都是独立的,都拥有其自己的生命周期,从一个实例的创建,数据初始化,挂载,更新,销毁.的一系列过程,就是一个实例的生命周期.
上官网图片
二.生命周期的钩子函数
vue一整个的生命周期中会有很多钩子函数提供给我们在vue生命周期不同的时刻进行操作,也就是说
在生命周期的不同阶段,会有自动执行的函数,这个函数叫做生命周期的钩子函数
1.生命周期的三个阶段
初始挂载阶段
- beforeCreate
- created
- beforeMount
- mounted
更新阶段
- beforeUpdate
- updated
销毁阶段
-
beforeDestroy
-
destroyed
2.生命周期的钩子函数释义
-
beforeCreate 实例创建之前触发一次
-
created 实例创建完成 触发一次
-
beforeMount 实例挂载到页面之前,挂载前触发一次
-
mounted 实例挂载到页面之后,挂载完成 触发一次
-
beforeUpdate 实例数据更新之前 可能触发多次
-
updated 实例数据更新之前 可能触发多次
-
beforeDestroy 实例销毁之前 触发一次
-
destroyed 实例销毁完成 触发一次
3.生命周期钩子函数详解
beforeCreate 实例创建之前
实例创建之前
- 获取不到 vm.$el (实例属性, 当前挂载点的根元素)
- 获取不到vm.$data(实例属性,当前配置项中的data结构中的数据)
- 一个生命周期过程中,只会触发一次
此钩子函数,一般没什么大用,不用在此钩子函数中做相应操作
const vm = new Vue({
el: '#app',
data: {
name: 'lechar'
},
methods: {
show() {
console.log("能够调用methods的数据了");
}
},
//实例创建之前触发
beforeCreate() {
console.log('beforeCreate 实例创建之前');
// vm.$el 当前挂载点的根元素
//vm.$data 当前配置项的data数据
console.log(this.$el);//此阶段无法获取vm.$el 实例属性
console.log(this.$data);//也无法获取 vm.$data 实例属性
// 此钩子函数一般没什么大用,不用做相应操作
}
});
created 实例创建完成
实例创建完成
- 获取不到 vm.$el
- 能获取到 vm.$data
- 能调用methods里的方法
- 一个生命周期中,只会执行一次
这里可以用于发送ajax请求,获取页面一打开就需要的数据
const vm = new Vue({
el: '#app',
data: {
name: 'lechar'
},
methods: {
show() {
console.log("能够调用methods的数据了");
}
},
//实例创建完成触发
created() {
console.log("created 实例创建完成触发");
console.log(this.$el);//此阶段无法获取vm.$el 实例属性
console.log(this.$data);//实例创建完成,可以获取到data数据了
this.show();//此时也可以调用methods里的数据了
// 此钩子函数可以去请求数据,比如ajax请求,得到页面开始需要的数据
}
});
那么有个问题,在beforeCreate中能发送ajax请求吗?
理论上来说是不可以的,原因是ajax请求数据之后我们是需要将数据赋值给配置项中的data中定义的某个数据的.因为在beforeCreate的时候,是无法获取到data中的数据的,更别说赋值了,但是呢,实际上是可以的,如果要深究的话,我们知道,ajax是异步的操作,当异步完成的时候,vue的生命周期肯定已经进入了后续阶段(mounted)都完成了的.在后续阶段,我们是可以修改data中的数据的.
$.ajax({
type:'get',
url:"/",
success:function(){
//异步的回调
}
});
beforeMount 实例挂载之前
实例挂载之前
- 通过vm.$el获取不到真实的dom ()
- 可以获取到data的数据和methods的方法了(实例创建完成都可以,这里当然可以)
- 一个生命周期,只触发一次
此钩子函数,一般没什么大用,不用在此钩子函数中做相应操作
<div id="app">
{{name}}
</div>
const vm = new Vue({
el: '#app',
data: {
name: 'lechar'
},
methods: {
show() {
console.log("能够调用methods的数据了");
}
},
//实例挂载之前触发
beforeMount() {
console.log("beforeMount 实例挂载之前触发");
console.log(this.$el);//不能获取到真实的dom,比如上面会输出没有编译过的代码
/**
* 直接输出这个:<div id="app">
* {{name}}
* </div>
*
*/
}
});
mounted 实例挂载完成
实例挂载完成
- 能获取到真实的dom了 是编译通过计算通过之后的真实dom
- 可以获取到data的数据和methods的方法了(实例创建完成都可以,这里当然可以)
- 一个生命周期,只触发一次
初始化与dom相关的操作需要放在这里,比如Swiper的实例化
const vm = new Vue({
el: '#app',
data: {
name: 'lechar'
},
methods: {
show() {
console.log("能够调用methods的数据了");
}
},
//实例挂载完成触发
mounted() {
console.log("mounted 实例挂载完成触发");
console.log(this.$el);//此时能获取到真实的dom了
//此钩子函数一般处理dom初始化相关的操作,比如Swiper的实例化
}
});
beforeUpdate 实例更新之前
实例更新之前
- 能获取到实例更细之前的dom,无法获取更新之后的dom
- !!!不能在这里做修改数据的操作,和ajax异步操作,因为会造成死循环
此钩子函数,一般没什么大用,不用在此钩子函数中做相应操作
const vm = new Vue({
el: '#app',
data: {
name: 'lechar'
},
methods: {
show() {
console.log("能够调用methods的数据了");
}
},
//实例更新之前触发(一个生命周期会触发多次)
beforeUpdate(){
console.log("beforeUpdate 实例更新之前触发");
console.log(this.$el.innerHTML);//能获取到实例更细之前的dom,无法获取更新之后的dom
//!!!不能在这里做修改数据的操作,和ajax异步操作,因为会造成死循环
//想想:我这里做个修改数据的操作,然后就进这个钩子函数,然后又修改,然后又进来....
}
});
updated 实例更新完成
实例更新完成
- 能得到数据更新之后 dom
- 一个生命周期过程中,会触发多次
- !!!不能在这里做修改数据的操作,和ajax异步操作,因为会造成死循环
此钩子函数,一般用于dom更新之后的操作,比如Swiper的更新
const vm = new Vue({
el: '#app',
data: {
name: 'lechar'
},
methods: {
show() {
console.log("能够调用methods的数据了");
}
},
//实例更新完成触发
updated() {
console.log("updated 实例更新完成触发");
console.log(this.$el.innerHTML);//能得到数据更新之后的dom
//此钩子函数,一般用于dom更新之后的操作,比如Swiper的更新
}
});
beforeDestroy 实例销毁之前触发
实例销毁之前触发
- 做一些销毁工作,比如计时器的清除,全局事件绑定的销毁
这个钩子函数一般用于销毁工作
const vm = new Vue({
el: '#app',
data: {
name: 'lechar'
},
methods: {
show() {
console.log("能够调用methods的数据了");
}
},
//实例销毁之前触发
beforeDestroy() {
console.log("beforeDestroy 实例销毁之前触发");
//清除定时器
clearInterval(this.timer);
// 清除全局滚动监听
window.removeEventListener("scroll", this.onScroll);
// 此钩子函数一般用于销毁工作,比如清除定时器,全局的绑定事件
}
});
destroyed 实例销毁完成
实例销毁完成
- 解除事件监听,数据绑定
此钩子函数,一般没什么大用,不用做相应操作
4.与声明周期钩子函数相关的几个实例属性
vm.$el 实例属性 。是当前实例的根的DOM对象
实例挂载之前 beforeMount 就可以得到 此实例属性了, beforeCreate和created是无法得到的
vm.$data 实例属性,是当前实例中data中定义的数据
实例创建完成 created 可以得到此实例属性,beforeCreate无法得到f
vm.$destroy() 实例方法 销毁实例的
调用之后,会触发 beforeDestroy 与 destroyed 两个生命周期的钩子函数
vm.$mount() 手动的挂载一个未挂载的实例
当如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。可以使用
vm.$mount()
手动地挂载一个未挂载的实例。
const vm = new Vue({
//注释掉,创建vue实例时不挂载元素,未挂载状态
//el: '#app',
data: {
name: 'lechar'
},
methods: {
show() {
console.log("show方法");
}
},
mounted() {
//实例挂载完成之后触发
console.log("实例挂载完成之后触发");
}
});
//浏览器页面 vm.$mount('#app'); 会触发mounted
vm.$nextTick 实例方法 数据更新之后,在dom中渲染完成,立即执行此函数
使用场景:Vue生命周期的created()钩子函数进行的DOM操作一定要放在vm.$nextTick()的回调函数中,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,所以此处一定要将DOM操作的js代码放进此函数的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载已完成。
通俗的理解:更改数据后当你想立即使用js操作新的dom的时候需要使用它
三.总结
vue的生命周期就是一个实例从创建到销毁的一个过程,一种机制. 在这个钩子函数,我们需要避免使用箭头函数,因为会带来一系列的this问题.