模式切换
生命周期
Vue 3 生命周期钩子函数在 setup()
函数中使用,提供了更灵活的逻辑组织方式。
主要生命周期钩子
setup()
调用时机:组件实例被创建时,在 beforeCreate
之前调用
用途:
- Composition API 的入口点
- 定义响应式数据、计算属性、方法等
- 返回的对象将暴露给模板和组件实例
javascript
setup(props, context) {
// props 是响应式的,不能解构
// context 包含 attrs, slots, emit
return {
// 暴露给模板的数据和方法
}
}
onBeforeMount()
调用时机:在挂载开始之前被调用
用途:
- 在组件首次渲染到 DOM 前执行
- 此时模板和渲染函数已编译,但尚未挂载到 DOM
javascript
import { onBeforeMount } from 'vue'
setup() {
onBeforeMount(() => {
console.log('组件即将挂载')
})
}
onMounted()
调用时机:组件挂载到 DOM 后调用
用途:
- 访问 DOM 元素
- 执行需要 DOM 存在的操作(如初始化第三方库)
- 发起 API 请求
javascript
import { onMounted } from 'vue'
setup() {
onMounted(() => {
console.log('组件已挂载')
const el = document.getElementById('my-element')
// 操作 DOM
})
}
onBeforeUpdate()
调用时机:响应式数据变化后,DOM 更新前调用
用途:
- 在 DOM 重新渲染前访问当前状态
- 用于调试或记录更新前的状态
javascript
import { onBeforeUpdate } from 'vue'
setup() {
onBeforeUpdate(() => {
console.log('数据已变化,DOM 即将更新')
})
}
onUpdated()
调用时机:DOM 更新完成后调用
用途:
- 执行依赖于更新后 DOM 的操作
- 注意:避免在此钩子中修改状态,可能导致无限循环
javascript
import { onUpdated } from 'vue'
setup() {
onUpdated(() => {
console.log('DOM 已更新')
})
}
onBeforeUnmount()
调用时机:组件卸载前调用
用途:
- 清理定时器、取消事件监听、取消订阅等
- 防止内存泄漏
javascript
import { onBeforeUnmount } from 'vue'
setup() {
const timer = setInterval(() => {
// 一些操作
}, 1000)
onBeforeUnmount(() => {
clearInterval(timer)
console.log('组件即将卸载')
})
}
onUnmounted()
调用时机:组件卸载后调用
用途:
- 执行最后的清理工作
- 组件及其所有子组件都已卸载
javascript
import { onUnmounted } from 'vue'
setup() {
onUnmounted(() => {
console.log('组件已卸载')
})
}
onErrorCaptured()
调用时机:捕获来自后代组件的错误时调用
用途:
- 错误处理
- 可以返回
false
阻止错误继续向上传播
javascript
import { onErrorCaptured } from 'vue'
setup() {
onErrorCaptured((err, instance, info) => {
console.error('捕获到错误:', err)
console.log('组件实例:', instance)
console.log('错误信息:', info)
// 阻止错误继续向上传播
return false
})
}
onActivated 和 onDeactivated
调用时机:与 <keep-alive>
缓存组件相关
用途:
onActivated
: 被 keep-alive 缓存的组件激活时调用onDeactivated
: 被 keep-alive 缓存的组件停用时调用
javascript
import { onActivated, onDeactivated } from 'vue'
setup() {
onActivated(() => {
console.log('组件被激活')
})
onDeactivated(() => {
console.log('组件被停用')
})
}
onRenderTracked 和 onRenderTriggered
调用时机:开发模式下调试用
用途:
onRenderTracked
: 跟踪虚拟 DOM 重新渲染时调用,记录哪些依赖项被跟踪onRenderTriggered
: 当依赖项触发组件重新渲染时调用
javascript
import { onRenderTracked, onRenderTriggered } from 'vue'
setup() {
onRenderTracked((event) => {
console.log('依赖被跟踪:', event)
})
onRenderTriggered((event) => {
console.log('依赖触发渲染:', event)
})
}
生命周期完整流程
初始化阶段
setup()
beforeCreate
(Options API)created
(Options API)
挂载阶段
onBeforeMount
- 编译模板/渲染函数
- 创建虚拟 DOM
- 挂载到真实 DOM
onMounted
更新阶段
- 数据变化
onBeforeUpdate
- 重新渲染虚拟 DOM
- 打补丁到真实 DOM
onUpdated
卸载阶段
onBeforeUnmount
- 卸载组件
onUnmounted
使用建议
- 在
setup
中组织代码:将相关逻辑放在一起,而不是分散在不同的生命周期中 - 避免在
onUpdated
中修改状态:可能导致无限更新循环 - 清理副作用:在
onBeforeUnmount
或onUnmounted
中清理定时器、事件监听等 - 组合式函数:可以将生命周期逻辑封装到可重用的组合式函数中
javascript
// 示例:封装一个使用生命周期的组合式函数
function useFetchData(url) {
const data = ref(null)
const error = ref(null)
onMounted(async () => {
try {
const response = await fetch(url)
data.value = await response.json()
} catch (e) {
error.value = e
}
})
return { data, error }
}
// 在组件中使用
setup() {
const { data, error } = useFetchData('/api/data')
return { data, error }
}