每个 Vue 实例都有一个完整的生命周期:从创建、挂载、更新到销毁。在这个过程中,Vue 提供了一系列钩子函数,让你可以在特定阶段执行代码。
理解生命周期是深入 Vue 的关键。它解释了组件什么时候初始化数据、什么时候可以访问 DOM、什么时候应该清理资源。
生命周期是 Vue 实例从诞生到消亡的完整过程。就像人的生老病死,Vue 实例也经历着:
创建 → 挂载 → 更新 → 销毁
每个阶段都有对应的钩子函数:
| 阶段 | 钩子函数 | 说明 |
|---|---|---|
| 创建 | beforeCreate, created | 实例初始化 |
| 挂载 | beforeMount, mounted | DOM 渲染 |
| 更新 | beforeUpdate, updated | 数据变化 |
| 销毁 | beforeDestroy, destroyed | 实例销毁 |
生命周期钩子让你能够:
1. 初始化时机控制
new Vue({
data: {
users: []
},
created() {
this.fetchUsers()
},
methods: {
async fetchUsers() {
const response = await fetch('/api/users')
this.users = await response.json()
}
}
})
2. DOM 操作时机
new Vue({
mounted() {
this.initChart()
},
methods: {
initChart() {
const canvas = this.$refs.canvas
new Chart(canvas, this.chartConfig)
}
}
})
3. 资源清理
new Vue({
data() {
return {
timer: null
}
},
mounted() {
this.timer = setInterval(() => {
this.refresh()
}, 5000)
},
beforeDestroy() {
clearInterval(this.timer)
}
})
Vue 的生命周期钩子可以分为四类:
创建阶段是实例初始化的过程,此时还没有开始渲染 DOM。
new Vue({
beforeCreate() {
console.log('实例初始化之前')
console.log(this.message)
},
created() {
console.log('实例创建完成')
console.log(this.message)
},
data: {
message: 'Hello'
}
})
挂载阶段将模板渲染成 DOM。
new Vue({
beforeMount() {
console.log('挂载之前')
console.log(this.$el)
},
mounted() {
console.log('挂载完成')
console.log(this.$el)
}
})
当数据变化时触发更新阶段。
new Vue({
beforeUpdate() {
console.log('数据变化,DOM 更新之前')
},
updated() {
console.log('DOM 更新完成')
}
})
实例销毁时触发。
new Vue({
beforeDestroy() {
console.log('实例即将销毁')
},
destroyed() {
console.log('实例已销毁')
}
})
组件同样拥有完整的生命周期:
Vue.component('my-component', {
template: '<div>{{ message }}</div>',
data() {
return {
message: 'Hello'
}
},
created() {
console.log('组件创建')
},
mounted() {
console.log('组件挂载')
},
beforeDestroy() {
console.log('组件即将销毁')
}
})
组件的生命周期与实例的生命周期遵循相同的规则。
被 keep-alive 缓存的组件有额外的钩子:
Vue.component('cached-component', {
template: '<div>内容</div>',
activated() {
console.log('组件被激活')
},
deactivated() {
console.log('组件被缓存')
}
})
Vue 提供了错误捕获钩子:
new Vue({
errorCaptured(err, vm, info) {
console.error('捕获到错误:', err)
console.error('错误来源:', info)
return false
}
})
1. 数据请求放在 created
created() {
this.loadData()
}
created 钩子在服务端渲染时也会执行,更适合数据初始化。
2. DOM 操作放在 mounted
mounted() {
this.$nextTick(() => {
this.initThirdPartyLibrary()
})
}
3. 清理工作放在 beforeDestroy
beforeDestroy() {
this.eventBus.$off('event', this.handler)
window.removeEventListener('resize', this.handleResize)
}
4. 避免在 updated 中修改数据
updated() {
this.counter++
}
这会导致无限循环。