文章目录
vue的生命周期
1. 生命周期
- Vue实例从创建到销毁的过程,就是生命周期
- 创建、初始化数据、编译模板、挂载DOM、渲染、更新、渲染、销毁等一系列过程
2. 周期阶段
Vue生命周期可以简单分为四个阶段:
- 创建阶段----> beforeCreate,created
- 挂载阶段----> beforeMount,mounted
- 运行阶段----> beforeUpdate,updated
- 销毁阶段----> beforeDestroy,destroyed
3. 生命周期详解
1. 创建阶段
1. beforeCreate
- beforeCreate是new Vue之后触发的第一个钩子函数,此时data、methods、computed、以及watch上的数据和方法还未初始化,都不能被访问
- 在初始化实例之后,数据观测和event\watcher事件配置之前被调用
2. created
- 数据据观测、property和方法的运算,watch、event事件回调
- data和methods初始化完成,异步请求适合在此钩子函数中调用
- 此时无法与Dom交互,如果必须则用this.$nextTick来访问
2. 挂载阶段
1. beforeMount
- template模板已经导入render函数编译,但未进行渲染
2. mounted
- DOM已经完成挂在,双向数据绑定,可以$refs属性对DOM进行操作
- 如果希望整个视图渲染完毕
mounted: function() {
this.$nextTick(function(){
})
}
3. 运行阶段
1. beforeUpdate
- beforeUpdate发生在响应式数据更新之前,虚拟DOM重新渲染之前被触发,
- 你可以在当前阶段进行更改数据,不会造成重新渲染,但会再次触发当前钩子函数
2. updated
- 此时DOM已经更新,现在可以执行依赖于DOM的操作
- 如果要相应状态改变,最好使用计算属性或 watcher 取而代之。最好不要在此期间更改数据,因为这可能会导致无限循环的更新。
- 如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick。
updated: function () {
this.$nextTick(function () {
// 代码将在整个视图重新渲染后执行
})
}
4. 摧毁阶段
1. beforeDestroy
- 实例销毁之前,在这期间实例完全可以被使用
- 在这时进行清楚定时器的操作
2. destroyed
- 实例被销毁、实例也被销毁、事件监听器被移除
生命周期钩子函数 | 实例处于阶段描述 | 能否获取到el (this.$el) | 能否获取到data (this.xxx) | 能否使用methods中的方法 (this.xxx()) |
---|---|---|---|---|
beforeCreate | 创建前 | 实例已初始化,但数据观测, | watch/event 事件回调还未配置 | 获取不到 |
created | 创建后 | 已完成如下配置,数据观测 (data observer),property 和方法的运算,watch/event 事件回调 | 获取不到 | 能 |
beforeMount | 挂载前 | dom已初始化,但并未挂载和渲染 | 能 | 能 |
mounted | 挂载后 | dom已完成挂载和渲染 能 | 能 | 能 |
beforeUpdate | 更新前 | 数据已改变,但dom为更新 能 | 能 | 能 |
updated | 更新后 | dom已更新 | 能 | 能 |
beforeDestroy | 销毁前 | 实例销毁前,实例仍然可用 | 能 | 能 |
destroyed | 销毁后 | 实例已销毁,所有指令被解绑,事件监听器被移除,子实例都被销毁 | 能 | 能 |
4. 周期Demo
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="UTF-8">
<script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>
<body>
<div id="app">
<p>{{ message }}</p>
<button @click="change()">change改变数据</button>
<button @click="destr()">destroy销毁实例</button>
<hr>
<button @click="getDom()">获取实例dom</button>
<button @click="getData()">获取实例data</button>
<button @click="getMethods()">获取实例methods</button>
</div>
<script type="text/javascript">
var obj = {"el: ": this.$el, "data: ":this.data}
function Life(name,el,data,methods){
this['生命周期钩子函数'] = name;
this['el (实例挂载的dom)'] = el;
this['data (实例的数据)'] = data;
this['methods (实例中的方法)'] = methods;
}
var app = new Vue({
el: '#app',
data: {
message: 66
},
beforeCreate: function () {
var obj = new Life('beforeCreate',this.$el,this.message,this.test)
console.table({'创建前':obj})
},
created: function () {
var obj = new Life('created',this.$el,this.message,this.test)
console.table({'创建后':obj})
},
beforeMount: function () {
var obj = new Life('beforeMount',this.$el,this.message,this.test)
console.table({'挂载前':obj})
alert('当前阶段处于 beforeMount ,此时虚拟 dom 已经创建完成,即将开始渲染。')
},
mounted: function () {
// 实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。
var obj = new Life('mounted',this.$el,this.message,this.test)
console.table({'挂载后':obj})
},
beforeUpdate: function () {
// 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
var obj = new Life('beforeUpdate',this.$el,this.message,this.test)
console.table({'数据更新,DOM 重新渲染前':obj})
alert('当前阶段处于 beforeUpdate ,此时实例中的数据已更新,但 dom 上的数据还未更新。')
},
updated: function () {
// 当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
var obj = new Life('updated',this.$el,this.message,this.test)
console.table({'数据更新,DOM 重新渲染后':obj})
// 注意 updated 不会保证所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick:
// 将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。
// 它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。
this.$nextTick(function () {
// DOM 现在更新了
// `this` 绑定到当前实例
console.log('这是 update 中的回调')
})
},
beforeDestroy: function () {
this.change()
// 实例销毁之前调用。在这一步,实例仍然完全可用。
var obj = new Life('beforeUpdate',this.$el,this.message,this.test)
console.table({'实例销毁前,此时实例还完全可用':obj})
},
destroyed: function () {
this.message = 123
// 实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
var obj = new Life('beforeUpdate',this.$el,this.message,this.test)
console.table({'实例销毁后':obj})
this.test()
},
methods: {
test() {
console.log('666')
},
change() {
this.message++;
console.log(this.message)
},
destr() {
this.$destroy();
},
getDom() {
console.log(this.$el)
},
getData() {
console.log(this.message)
},
getMethods() {
console.log(this.test)
}
}
})
</script>
</body>
</html>