Appearance
Vue 2 生命周期详解
什么是 Vue 生命周期
Vue 生命周期是指 Vue 实例从创建到销毁的整个过程,在此过程中会触发一系列的钩子函数(生命周期钩子)。这些钩子函数允许我们在不同阶段执行特定的操作,从而更好地控制和管理 Vue 实例。
Vue 2 生命周期钩子
1. 创建阶段
beforeCreate
- 执行时机:Vue 实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前。
- 作用:此时实例的属性和方法尚未初始化,无法访问
data、computed、methods等。 - 使用场景:通常用于初始化非响应式数据,或执行一些与 Vue 实例无关的操作。
javascript
new Vue({
beforeCreate() {
console.log('beforeCreate 钩子执行')
console.log('data:', this.message) // undefined
console.log('methods:', this.changeMessage) // undefined
},
data: {
message: 'Hello Vue!'
},
methods: {
changeMessage() {
this.message = 'Hello World!'
}
}
})created
- 执行时机:Vue 实例创建完成后执行,此时已完成数据观测、属性和方法的运算,以及 event/watcher 的回调。
- 作用:可以访问
data、computed、methods等,但 DOM 尚未生成,$el属性不可用。 - 使用场景:适合进行数据初始化、发起异步请求(如 API 调用)、设置监听器等操作。
javascript
new Vue({
created() {
console.log('created 钩子执行')
console.log('data:', this.message) // 'Hello Vue!'
console.log('methods:', this.changeMessage) // 函数定义
// 发起异步请求
axios.get('/api/data').then(response => {
this.data = response.data
})
},
data: {
message: 'Hello Vue!',
data: {}
},
methods: {
changeMessage() {
this.message = 'Hello World!'
}
}
})2. 挂载阶段
beforeMount
- 执行时机:在挂载开始之前执行,此时模板已编译完成,但尚未挂载到 DOM 上。
- 作用:可以获取编译后的模板,但 DOM 尚未更新。
- 使用场景:可用于最后一次修改模板数据的机会。
javascript
new Vue({
beforeMount() {
console.log('beforeMount 钩子执行')
console.log('$el:', this.$el) // 已存在但未挂载
// 最后一次修改数据
this.message = '修改后的消息'
},
data: {
message: 'Hello Vue!'
}
})mounted
- 执行时机:挂载完成后执行,此时 Vue 实例已挂载到 DOM 上,
$el属性可用。 - 作用:可以访问和操作 DOM 元素,执行依赖于 DOM 的操作。
- 使用场景:适合初始化需要 DOM 的第三方库(如图表库、地图库)、绑定事件监听器等。
javascript
new Vue({
mounted() {
console.log('mounted 钩子执行')
console.log('$el:', this.$el) // 已挂载到 DOM
// 初始化第三方库
this.initChart()
},
methods: {
initChart() {
// 假设使用 ECharts
const chart = echarts.init(this.$el.querySelector('#chart'))
chart.setOption({
// 配置项
})
}
}
})3. 更新阶段
beforeUpdate
- 执行时机:数据更新后,DOM 更新前执行。
- 作用:可以获取更新前的 DOM 状态,或执行一些在 DOM 更新前需要的操作。
- 使用场景:适合在数据变化但 DOM 未更新时进行操作,如获取更新前的 DOM 尺寸、位置等。
javascript
new Vue({
beforeUpdate() {
console.log('beforeUpdate 钩子执行')
console.log('更新前的 DOM 内容:', this.$el.textContent)
},
data: {
message: 'Hello Vue!'
}
})updated
- 执行时机:DOM 更新完成后执行。
- 作用:可以获取更新后的 DOM 状态,执行依赖于 DOM 更新的操作。
- 使用场景:适合在 DOM 更新后执行操作,如重新计算 DOM 尺寸、位置,或更新第三方库的配置。
javascript
new Vue({
updated() {
console.log('updated 钩子执行')
console.log('更新后的 DOM 内容:', this.$el.textContent)
// 重新计算 DOM 尺寸
this.calculateSize()
},
methods: {
calculateSize() {
const height = this.$el.offsetHeight
console.log('元素高度:', height)
}
}
})4. 销毁阶段
beforeDestroy
- 执行时机:Vue 实例销毁前执行,此时实例仍完全可用。
- 作用:可以执行清理操作,如清除定时器、取消事件监听器、解绑第三方库等。
- 使用场景:适合进行资源释放,避免内存泄漏。
javascript
new Vue({
beforeDestroy() {
console.log('beforeDestroy 钩子执行')
// 清除定时器
clearInterval(this.timer)
// 取消事件监听器
window.removeEventListener('resize', this.handleResize)
},
mounted() {
this.timer = setInterval(() => {
console.log('定时器执行')
}, 1000)
window.addEventListener('resize', this.handleResize)
},
methods: {
handleResize() {
console.log('窗口大小变化')
}
}
})destroyed
- 执行时机:Vue 实例销毁后执行,此时实例的所有指令已解绑,事件监听器已移除,子实例也已销毁。
- 作用:可以执行最终的清理操作。
- 使用场景:通常用于确认实例已完全销毁,或执行一些与实例销毁相关的最终操作。
javascript
new Vue({
destroyed() {
console.log('destroyed 钩子执行')
console.log('实例已销毁')
}
})5. 特殊生命周期钩子
activated
- 执行时机:当使用
keep-alive包裹的组件被激活时执行。 - 作用:可以在组件被激活时执行操作。
- 使用场景:适合在组件被重新激活时进行数据刷新或状态重置。
javascript
new Vue({
activated() {
console.log('activated 钩子执行')
// 刷新数据
this.fetchData()
},
methods: {
fetchData() {
// 重新获取数据
}
}
})deactivated
- 执行时机:当使用
keep-alive包裹的组件被停用时执行。 - 作用:可以在组件被停用时执行清理操作。
- 使用场景:适合在组件被停用时保存状态或执行清理。
javascript
new Vue({
deactivated() {
console.log('deactivated 钩子执行')
// 保存状态
this.saveState()
},
methods: {
saveState() {
// 保存当前状态
}
}
})生命周期执行顺序
Vue 实例的生命周期执行顺序如下:
- 创建阶段:
beforeCreate→created - 挂载阶段:
beforeMount→mounted - 更新阶段:
beforeUpdate→updated(数据变化时触发) - 销毁阶段:
beforeDestroy→destroyed(实例销毁时触发) - 特殊阶段:
activated(组件被激活时触发)→deactivated(组件被停用时触发)
生命周期钩子的使用建议
1. 数据初始化和异步请求
- created:适合进行数据初始化、发起异步请求(如 API 调用)。
- 原因:此时已可访问
data和methods,但 DOM 尚未挂载,避免了不必要的 DOM 操作。
2. DOM 操作和第三方库初始化
- mounted:适合执行依赖于 DOM 的操作,如初始化第三方库(图表、地图等)。
- 原因:此时 DOM 已挂载,可直接访问和操作 DOM 元素。
3. 数据更新前后的操作
- beforeUpdate:适合在 DOM 更新前获取状态,如获取更新前的 DOM 尺寸。
- updated:适合在 DOM 更新后执行操作,如重新计算尺寸或更新第三方库。
4. 资源清理
- beforeDestroy:适合执行清理操作,如清除定时器、取消事件监听器、解绑第三方库。
- 原因:此时实例仍可用,可以访问需要清理的资源。
5. 组件激活和停用
- activated:适合在组件被激活时刷新数据或重置状态。
- deactivated:适合在组件被停用时保存状态或执行清理。
示例:完整的生命周期演示
javascript
new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
count: 0
},
beforeCreate() {
console.log('1. beforeCreate: 实例初始化前')
console.log('data:', this.message) // undefined
},
created() {
console.log('2. created: 实例创建完成')
console.log('data:', this.message) // 'Hello Vue!'
// 发起异步请求
setTimeout(() => {
this.message = '从 API 获取的数据'
}, 1000)
},
beforeMount() {
console.log('3. beforeMount: 挂载前')
console.log('$el:', this.$el)
},
mounted() {
console.log('4. mounted: 挂载完成')
console.log('$el:', this.$el)
// 初始化定时器
this.timer = setInterval(() => {
this.count++
}, 1000)
},
beforeUpdate() {
console.log('5. beforeUpdate: 更新前')
console.log('count:', this.count)
},
updated() {
console.log('6. updated: 更新完成')
console.log('count:', this.count)
},
beforeDestroy() {
console.log('7. beforeDestroy: 销毁前')
// 清除定时器
clearInterval(this.timer)
},
destroyed() {
console.log('8. destroyed: 销毁完成')
}
})总结
Vue 2 的生命周期钩子提供了在不同阶段执行操作的能力,使我们能够更好地控制和管理 Vue 实例。通过合理使用这些钩子,我们可以:
- 在适当的时机初始化数据和发起请求
- 执行依赖于 DOM 的操作和第三方库初始化
- 在数据更新前后执行相应的操作
- 及时清理资源,避免内存泄漏
- 处理组件的激活和停用状态
理解和掌握 Vue 2 的生命周期,对于构建高效、可维护的 Vue 应用至关重要。在实际开发中,应根据具体需求选择合适的生命周期钩子来执行相应的操作,以确保应用的性能和稳定性。