当前位置: 首页 > news >正文

Vue 3 生命周期钩子详解

一、生命周期概述

1.1 什么是生命周期

Vue组件从创建到销毁的整个过程,Vue在关键时刻提供钩子函数,允许我们在特定阶段执行自定义逻辑。

1.2 生命周期图示

text
创建阶段:
setup() → onBeforeMount() → onMounted()更新阶段:
onBeforeUpdate() → onUpdated()卸载阶段:
onBeforeUnmount() → onUnmounted()错误处理:
onErrorCaptured() → onRenderTracked() → onRenderTriggered()

二、Composition API 生命周期钩子

2.1 导入和使用

import {onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted,onErrorCaptured,onActivated,onDeactivated,onRenderTracked,onRenderTriggered,onServerPrefetch
} from 'vue'

2.2 完整示例

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'const count = ref(0)
let timer = null// 组件挂载后执行
onMounted(() => {console.log('组件已挂载到DOM')// 启动定时器timer = setInterval(() => {count.value++}, 1000)// DOM操作const el = document.getElementById('my-element')if (el) {el.style.color = 'red'}// API请求
  fetchData()
})// 组件卸载前执行
onUnmounted(() => {console.log('组件即将卸载')// 清理定时器if (timer) {clearInterval(timer)timer = null}// 取消事件监听window.removeEventListener('resize', handleResize)
})async function fetchData() {// 数据获取逻辑
}
</script>

三、各个钩子的详细用法

3.1 创建阶段

<script setup>
import { ref, onBeforeMount, onMounted } from 'vue'const data = ref(null)// setup() 阶段 - Composition API的入口
console.log('1. setup() 执行 - 响应式数据初始化')// 组件挂载到DOM之前
onBeforeMount(() => {console.log('2. onBeforeMount() - DOM尚未创建')// 此时无法访问DOM元素// 适合执行最后的初始化配置
})// 组件挂载到DOM之后
onMounted(() => {console.log('3. onMounted() - DOM已创建')console.log('组件根元素:', document.querySelector('#app'))// 可以访问DOMconst element = document.querySelector('.my-class')if (element) {element.style.color = 'blue'}// 适合执行:// 1. DOM操作// 2. 异步数据请求// 3. 事件监听// 4. 定时器window.addEventListener('resize', handleResize)
})
</script><template><div ref="container">内容</div>
</template>

3.2 更新阶段

<script setup>
import { ref, watch, onBeforeUpdate, onUpdated } from 'vue'const count = ref(0)
const updateCount = ref(0)// 数据更新前执行(DOM更新前)
onBeforeUpdate(() => {console.log('4. onBeforeUpdate() - 数据变化,DOM更新前')console.log('当前count:', count.value)console.log('DOM中的count:', document.querySelector('#count').textContent)// 此时DOM还是旧的状态// 适合获取更新前的DOM状态const oldHeight = document.querySelector('#container').offsetHeightconsole.log('更新前高度:', oldHeight)
})// 数据更新后执行(DOM更新后)
onUpdated(() => {console.log('5. onUpdated() - DOM更新完成')console.log('DOM中的count:', document.querySelector('#count').textContent)// 此时DOM已更新// 适合执行依赖新DOM的操作const newHeight = document.querySelector('#container').offsetHeightconsole.log('更新后高度:', newHeight)// 注意:避免在这里修改响应式数据,可能导致无限循环updateCount.value++
})// 手动触发更新
function increment() {count.value++
}
</script><template><div id="container"><p id="count">{{ count }}</p><button @click="increment">增加</button><p>更新次数: {{ updateCount }}</p></div>
</template>

3.3 卸载阶段

<!-- 父组件 -->
<script setup>
import { ref, shallowRef } from 'vue'
import ChildComponent from './ChildComponent.vue'const showChild = ref(true)
const childKey = ref(1)function toggleChild() {showChild.value = !showChild.value
}function remountChild() {showChild.value = falsesetTimeout(() => {childKey.value++showChild.value = true}, 100)
}
</script><template><button @click="toggleChild">切换子组件</button><button @click="remountChild">重新挂载</button><ChildComponent v-if="showChild" :key="childKey" />
</template><!-- 子组件 ChildComponent.vue -->
<script setup>
import { onBeforeUnmount, onUnmounted } from 'vue'// 组件卸载前
onBeforeUnmount(() => {console.log('6. onBeforeUnmount() - 组件即将卸载')// 此时组件实例仍然可用// 适合清理不依赖DOM的资源
})// 组件卸载后
onUnmounted(() => {console.log('7. onUnmounted() - 组件已卸载')// 此时组件实例已销毁// 适合执行:// 1. 清理定时器// 2. 取消事件监听// 3. 清除缓存// 4. 取消网络请求
})
</script>

3.4 错误处理钩子

<script setup>
import { onErrorCaptured } from 'vue'// 捕获后代组件的错误
onErrorCaptured((error, instance, info) => {console.error('8. onErrorCaptured() - 捕获到错误')console.error('错误对象:', error)console.error('组件实例:', instance)console.error('错误信息:', info)// 可以在此处:// 1. 错误上报// 2. 显示错误界面// 3. 阻止错误继续传播(返回false)// 返回false阻止错误向上传播return false
})// 开发调试钩子
import { onRenderTracked, onRenderTriggered } from 'vue'// 追踪响应式依赖
onRenderTracked((event) => {console.log('依赖被追踪:', event)
})// 响应式触发重新渲染
onRenderTriggered((event) => {console.log('重新渲染被触发:', event)
})
</script>

3.5 KeepAlive 缓存组件钩子

<script setup>
import { onActivated, onDeactivated } from 'vue'// 当被 <KeepAlive> 缓存的组件激活时
onActivated(() => {console.log('组件被激活 (activated)')// 恢复组件状态// 重新启动定时器// 重新获取数据
})// 当被 <KeepAlive> 缓存的组件停用时
onDeactivated(() => {console.log('组件被停用 (deactivated)')// 保存组件状态// 暂停定时器// 清理临时数据
})
</script>

3.6 SSR 服务端渲染钩子

<script setup>
import { onServerPrefetch } from 'vue'const data = ref(null)// 服务端数据预取
onServerPrefetch(async () => {console.log('服务端预取数据')data.value = await fetchServerData()
})async function fetchServerData() {// 服务端数据获取逻辑return await fetch('/api/data').then(res => res.json())
}
</script>

四、Options API 生命周期钩子

4.1 对比表

 
Composition APIOptions API执行时机
setup() beforeCreate() 实例初始化前
setup() created() 实例创建完成
onBeforeMount() beforeMount() 挂载前
onMounted() mounted() 挂载后
onBeforeUpdate() beforeUpdate() 更新前
onUpdated() updated() 更新后
onBeforeUnmount() beforeDestroy() 销毁前
onUnmounted() destroyed() 销毁后
onErrorCaptured() errorCaptured() 错误捕获

五、实际应用场景

5.1 数据请求最佳实践

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'const data = ref(null)
const loading = ref(false)
let abortController = nullonMounted(async () => {await fetchData()
})onUnmounted(() => {// 组件卸载时取消请求if (abortController) {abortController.abort()}
})async function fetchData() {// 取消之前的请求if (abortController) {abortController.abort()}abortController = new AbortController()loading.value = truetry {const response = await fetch('/api/data', {signal: abortController.signal})data.value = await response.json()} catch (error) {if (error.name !== 'AbortError') {console.error('请求失败:', error)}} finally {loading.value = false}
}
</script>

5.2 第三方库集成

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts'const chartRef = ref(null)
let chartInstance = nullonMounted(() => {// 初始化图表if (chartRef.value) {chartInstance = echarts.init(chartRef.value)updateChart()}// 监听窗口大小变化window.addEventListener('resize', handleResize)
})onUnmounted(() => {// 销毁图表实例if (chartInstance) {chartInstance.dispose()chartInstance = null}// 移除事件监听window.removeEventListener('resize', handleResize)
})function handleResize() {if (chartInstance) {chartInstance.resize()}
}function updateChart() {if (chartInstance) {chartInstance.setOption({// 图表配置
    })}
}
</script><template><div ref="chartRef" style="width: 600px; height: 400px;"></div>
</template>

5.3 性能优化技巧

<script setup>
import { ref, onMounted, onUnmounted, shallowRef } from 'vue'// 使用 shallowRef 减少不必要的响应式
const largeData = shallowRef({/* 大数据对象 */})onMounted(() => {// 使用 requestAnimationFrame 优化DOM操作requestAnimationFrame(() => {// DOM操作
  })// 防抖处理频繁事件window.addEventListener('scroll', debounce(handleScroll, 100))
})onUnmounted(() => {// 清理防抖函数window.removeEventListener('scroll', debounce(handleScroll, 100))
})function debounce(fn, delay) {let timer = nullreturn function(...args) {if (timer) clearTimeout(timer)timer = setTimeout(() => fn.apply(this, args), delay)}
}
</script>

六、常见问题和注意事项

6.1 生命周期执行顺序

javascript
// 父组件和子组件的生命周期顺序
父 beforeCreate → 父 created → 父 beforeMount
子 beforeCreate → 子 created → 子 beforeMount → 子 mounted
父 mounted// 更新顺序
父 beforeUpdate → 子 beforeUpdate → 子 updated → 父 updated// 卸载顺序
父 beforeUnmount → 子 beforeUnmount → 子 unmounted → 父 unmounted

6.2 异步操作注意事项

<script setup>
import { onMounted } from 'vue'onMounted(async () => {// 正确:使用 await
  await fetchData()// 注意:如果不需要等待,可以直接调用
  fetchDataWithoutAwait()// 错误:不能直接使用 async 返回值// const result = await fetchData() // 这行没问题// 但 onMounted 本身返回 Promise 可能导致问题
})// 更好的做法
onMounted(() => {loadData()
})async function loadData() {// 异步逻辑
}
</script>

6.3 内存泄漏预防

<script setup>
import { onUnmounted } from 'vue'// 需要清理的资源
let resources = []onUnmounted(() => {// 清理所有资源resources.forEach(resource => {if (resource.dispose) resource.dispose()if (resource.abort) resource.abort()if (resource.removeEventListener) {// 移除事件监听
    }})resources = []// 清理全局事件window.removeEventListener('resize', handleResize)document.removeEventListener('click', handleClick)
})
</script>

七、总结

关键点:

  1. Composition API 钩子以 on 开头,在 setup() 中同步调用

  2. 挂载阶段 (onMounted):适合DOM操作和异步请求

  3. 更新阶段 (onUpdated):谨慎使用,避免无限循环

  4. 卸载阶段 (onUnmounted):必须清理资源,防止内存泄漏

  5. 错误处理 (onErrorCaptured):用于错误边界处理

  6. KeepAlive 组件:使用 onActivated/onDeactivated 管理状态

最佳实践:

  • 在正确的生命周期执行相应的操作

  • 及时清理资源,防止内存泄漏

  • 避免在 onUpdated 中修改响应式数据

  • 使用异步操作时注意错误处理

  • 考虑使用 onServerPrefetch 进行SSR优化

通过合理使用生命周期钩子,可以更好地控制组件行为,优化性能,并避免常见的问题。

 
http://www.jsqmd.com/news/366266/

相关文章:

  • 2026-02-01
  • 分析有名的人力资源企业,蓝遇人才优势显著 - 工业品牌热点
  • P0926EQ FBM202逻辑控制器
  • 2026年水下清淤机器人:口碑好的厂家有哪些?目前水下清淤机器人上善环保发展迅速,实力雄厚 - 品牌推荐师
  • 想知道国内口碑好的防爆板厂家?2026厂家排行别错过,评价好的防爆板口碑推荐榜优选品牌推荐与解析 - 品牌推荐师
  • 零代码构建企业级RAG应用:Langflow可视化开发全指南
  • 品质为王,定义高端标准——2026高端家装电线品牌推荐榜 - 黑马榜单
  • 2026做得好的郭氏正骨排行榜,快看看有谁,郭氏正骨,郭氏正骨公司推荐排行 - 品牌推荐师
  • P0914SV FBM203隔离输入模块
  • 2026年靠谱的宠物训练公司推荐,广州佛山等地值得关注 - 工业设备
  • 口碑香氛OEM厂家2026年评测:品质与创新的碰撞,洗手间香薰/蜡片香氛/孕婴香薰,香氛OEM供应商推荐排行 - 品牌推荐师
  • 2026年2月口碑好的小程序开发企业推荐,这些值得关注!,网络公司/小程序开发/网站建设,小程序开发企业排行榜单 - 品牌推荐师
  • 新鲜发布!2026年1月水果分选机生产商靠谱排行,西瓜分选机/智能水果分选机/圣女果选果机,水果分选机公司推荐 - 品牌推荐师
  • 2025新中式高定服装加盟热,这些品牌成行业佼佼者!,新中式高定服装加盟需要多少钱赋能企业生产效率提升与成本优化 - 品牌推荐师
  • 必收藏!ReAct框架详解(Reasoning+Acting):让AI从“问答机器”升级为可信赖智能代理【小白程序员入门必备】
  • 2026年于洪服务好的车衣改色实体店价格,贴隐形车衣/车衣改色/太阳膜/隐形车衣/汽车贴膜/汽车车衣,车衣改色品牌多少钱 - 品牌推荐师
  • 2026年高密度硅酸钙板厂家实力榜,哪些值得选择?硅酸钙保温板/汽车后视镜热弯模具,高密度硅酸钙板厂家推荐排行 - 品牌推荐师
  • 字幕制作工具Aegisub全攻略:从入门到专业的视频字幕编辑之旅
  • 屏幕分辨率暴涨,游戏为何频频掉帧?
  • 数据恢复实力厂家口碑解析,助你找到可靠服务,介质预检恢复取证工作台/NAS数据恢复软件,数据恢复实力厂家推荐排行榜 - 品牌推荐师
  • 2026年行业内正规的气动葫芦供应商哪家权威,jdn气动葫芦/10吨气动葫芦/GDN气动葫芦,气动葫芦制造厂口碑推荐榜单 - 品牌推荐师
  • 在Linux系统搭建全能游戏平台
  • 2026怎么选新型舰艇模型制造企业?业内推荐来了,国内诚信的模型制造企业排名忠军装备引领行业标杆 - 品牌推荐师
  • What, Whether and How Unveiling Process Reward Models for Thinking with Images Reasoning
  • 2026市面上优质激素类试剂盒供应商对比,哪家更值得选?his elisa试剂盒/小鼠试剂盒,激素类试剂盒厂商排行 - 品牌推荐师
  • 拒绝高价智商税!平价又专业的GEO优化服务商盘点,垂直/全行业全覆盖 - 品牌推荐大师1
  • 2026电子取证,口碑好的介质预检恢复取证工作台品牌别选错,视频恢复取证工作站/数据恢复,电子取证实力厂家口碑排行 - 品牌推荐师
  • android transient
  • 2026年热门金相镶嵌机供应商盘点,选型不迷茫,手动金相磨抛机/金相显微镜软件,金相镶嵌机企业推荐排行榜 - 品牌推荐师
  • 探讨以网络教学考试为主导目标的学校,湖北开放大学实力如何 - 工业推荐榜