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

Vue.js 生命周期全面解析

什么是Vue生命周期

Vue生命周期指的是Vue实例从创建到销毁的整个过程中所经历的一系列阶段。在每个阶段,Vue都会提供特定的"钩子函数"(Lifecycle Hooks),允许开发者在不同阶段插入自定义代码,从而实现对Vue实例的精细控制。

理解Vue生命周期对于开发高效、可维护的Vue应用至关重要,它能帮助我们:

  1. 知道在何时执行特定操作(如数据获取、DOM操作等)

  2. 避免在不恰当的阶段执行操作导致的错误

  3. 优化应用性能

  4. 更好地调试和解决问题

Vue生命周期图示

在深入讲解各个生命周期钩子之前,先看一下官方提供的生命周期图示:

开始
│
├── 初始化阶段
│   ├── beforeCreate
│   └── created
│
├── 挂载阶段
│   ├── beforeMount
│   └── mounted
│
├── 更新阶段
│   ├── beforeUpdate
│   └── updated
│
├── 卸载阶段
│   ├── beforeUnmount (Vue 3) / beforeDestroy (Vue 2)
│   └── unmounted (Vue 3) / destroyed (Vue 2)
│
└── 激活阶段 (仅keep-alive组件)├── activated└── deactivated

生命周期钩子详解

1. 初始化阶段

beforeCreate
  • 调用时机:实例初始化之后,数据观测(data observer)和event/watcher事件配置之前被调用

  • 特点

    • 此时无法访问到data、computed、methods等选项

    • 常用于插件开发中执行一些初始化任务

export default {beforeCreate() {console.log('beforeCreate', this.$data); // undefinedconsole.log('beforeCreate', this.methodName); // undefined}
}
created
  • 调用时机:实例创建完成后被立即调用

  • 特点

    • 可以访问data、computed、methods等

    • 尚未挂载DOM,$el属性不可用

    • 常用于异步数据请求、初始化非响应式属性等

export default {data() {return {message: 'Hello Vue!'}},created() {console.log('created', this.message); // 'Hello Vue!'console.log('created', this.$el); // undefinedthis.fetchData(); // 常见的数据获取操作}
}

2. 挂载阶段

beforeMount
  • 调用时机:在挂载开始之前被调用,相关的render函数首次被调用

  • 特点

    • 模板已编译,但尚未将生成的DOM替换到页面中

    • 很少使用,但在服务端渲染时是唯一可用的钩子

export default {beforeMount() {console.log('beforeMount', this.$el); // 原始的挂载元素}
}
mounted
  • 调用时机:实例被挂载后调用

  • 特点

    • 可以访问到渲染后的DOM

    • 常用于需要操作DOM的库初始化(如图表库)

    • 注意:不保证所有子组件也都一起被挂载

export default {mounted() {console.log('mounted', this.$el); // 渲染后的DOM元素this.initChart(); // 初始化图表库}
}

3. 更新阶段

beforeUpdate
  • 调用时机:数据变化时,虚拟DOM重新渲染和打补丁之前调用

  • 特点

    • 可以在更新前访问现有的DOM状态

    • 适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器

export default {beforeUpdate() {console.log('beforeUpdate', this.message);}
}
updated
  • 调用时机:由于数据更改导致的虚拟DOM重新渲染和打补丁后调用

  • 特点

    • 可以执行依赖于DOM的操作

    • 注意:避免在此钩子中更改状态,可能导致无限更新循环

    • 不保证所有子组件也都一起被重绘

export default {updated() {console.log('updated', this.message);// 可以执行DOM相关操作,但要小心无限循环}
}

4. 卸载阶段

beforeUnmount (Vue 3) / beforeDestroy (Vue 2)
  • 调用时机:实例销毁之前调用

  • 特点

    • 实例仍然完全可用

    • 适合执行清理操作,如清除定时器、取消事件监听等

export default {beforeUnmount() { // Vue 3// 或 beforeDestroy() { // Vue 2clearInterval(this.timer);window.removeEventListener('resize', this.handleResize);}
}
unmounted (Vue 3) / destroyed (Vue 2)
  • 调用时机:实例销毁后调用

  • 特点

    • 所有指令都已解绑,所有事件监听器都已移除

    • 所有子实例也都被销毁

export default {unmounted() { // Vue 3// 或 destroyed() { // Vue 2console.log('组件已销毁');}
}

5. 缓存组件相关钩子 (keep-alive)

activated
  • 调用时机:被keep-alive缓存的组件激活时调用

  • 特点

    • 适合执行需要在组件显示时刷新的操作

export default {activated() {this.fetchData(); // 重新获取数据}
}
deactivated
  • 调用时机:被keep-alive缓存的组件失活时调用

  • 特点

    • 适合保存组件状态或清除占用资源的操作

export default {deactivated() {this.saveState(); // 保存组件状态}
}

Vue 2与Vue 3生命周期对比

Vue 2Vue 3说明
beforeCreatebeforeCreate基本相同
createdcreated基本相同
beforeMountbeforeMount基本相同
mountedmounted基本相同
beforeUpdatebeforeUpdate基本相同
updatedupdated基本相同
beforeDestroybeforeUnmount功能相同,名称更语义化
destroyedunmounted功能相同,名称更语义化
-renderTrackedVue 3新增,调试用
-renderTriggeredVue 3新增,调试用
errorCapturederrorCaptured错误捕获,Vue 3有变化

生命周期最佳实践

1、数据获取

  • 使用created或mounted获取初始数据
  • 对于SSR应用,使用created

2、DOM操作

  • 必须在mounted之后进行
  • 避免在updated中进行DOM操作,可能导致无限循环

3、清理工作

  • 在beforeUnmount/beforeDestroy中清除定时器、事件监听等

4、性能优化

  • 避免在频繁触发的钩子(如updated)中执行重操作

5、组件通信

  • 父组件的mounted不保证子组件已挂载,使用$nextTick确保

常见问题与解决方案

1、为什么在created中获取不到DOM元素?

  • 因为此时模板还未编译和挂载,应在mounted中操作DOM

2、mounted不保证所有子组件都挂载怎么办?

  • 使用this.$nextTick确保所有子组件已渲染
mounted() {this.$nextTick(() => {// 这里可以确保所有子组件都已挂载});
}

3、如何在组件销毁前保存状态?

  • 在beforeUnmount/beforeDestroy中保存需要持久化的状态

4、为什么updated中修改数据可能导致无限循环?

  • 因为数据修改会触发更新,更新又会调用updated,形成循环

总结

Vue生命周期是Vue框架的核心概念之一,理解并正确使用各个生命周期钩子能够帮助我们:

  • 在正确的时机执行代码

  • 避免常见错误和性能问题

  • 构建更健壮、可维护的Vue应用

随着Vue 3的推出,生命周期钩子名称更加语义化,并增加了新的调试钩子,但核心概念保持不变。掌握这些知识将为你开发高质量的Vue应用奠定坚实基础。

http://www.xdnf.cn/news/900829.html

相关文章:

  • Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
  • 第三方测试机构进行科技成果鉴定测试有什么价值
  • 使用Python和OpenCV实现图像识别与目标检测
  • 20250606-C#知识:List排序
  • 32单片机——窗口看门狗
  • 青少年编程与数学 01-011 系统软件简介 05 macOS操作系统
  • java 实现excel文件转pdf | 无水印 | 无限制
  • 大故障:阿里云核心域名爆炸了
  • 在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
  • Qt客户端技巧 -- 窗口美化 -- 窗口阴影
  • linux 故障处置通用流程-36计-28-37
  • 设计模式——模板方法
  • 基于 JavaSE 实现(GUI)的 小型ATM 银行模拟系统
  • [特殊字符]解决 “IDEA 登录失败。不支持早于 14.0 的 GitLab 版本” 问题的几种方法
  • LangChain【6】之输出解析器:结构化LLM响应的关键工具
  • [ElasticSearch] DSL查询
  • 【Spark征服之路-2.3-Spark运行架构】
  • OpenLayers 分屏对比(地图联动)
  • 【 java 集合知识 第二篇 】
  • CSS 定位:原理 + 场景 + 示例全解析
  • 使用 SymPy 进行向量和矩阵的高级操作
  • uni-app 如何实现选择和上传非图像、视频文件?
  • 山东大学《数据可视化》期末复习宝典
  • 机器学习框架PyTorch
  • Opencv中的copyto函数
  • ESP8266(NodeMcu)+GPS模块+TFT屏幕实现GPS码表
  • 关于双网卡优先级:有效跃点数的解析(设置值×2)
  • day48 python通道注意力
  • 基于AWS Serverless架构:零运维构建自动化SEO内容生成系统
  • Spark 之 DataFrame 开发