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

Vue 生命周期详解

Vue 组件的生命周期是理解 Vue 工作原理的核心概念之一。下面我将详细解释 Vue 的生命周期,并特别说明何时可以访问 data 数据。

完整的 Vue 生命周期图示

创建阶段:
beforeCreate → created → beforeMount → mounted更新阶段:
beforeUpdate → updated销毁阶段:
beforeDestroy → destroyed (Vue 2)
beforeUnmount → unmounted (Vue 3)

生命周期钩子详解

1. beforeCreate

  • 调用时机:实例初始化之后,数据观测和事件配置之前

  • 特点

    • 无法访问到 data、computed、methods 等

    • 组件实例的 data 和 methods 尚未初始化

2. created ✅ 可以首次访问 data

  • 调用时机:实例创建完成后

  • 特点

    • 可以访问 data、computed、methods 等

    • 尚未挂载到 DOM,无法访问 $el

    • 常用于异步数据请求、初始化数据

3. beforeMount

  • 调用时机:挂载开始之前

  • 特点

    • 可以访问 data,但模板尚未编译为 DOM

    • $el 尚不可用

4. mounted ✅ 可以访问 DOM 元素

  • 调用时机:实例挂载到 DOM 后

  • 特点

    • 可以访问到渲染后的 DOM 元素 ($el)

    • 所有同步子组件已挂载

    • 常用于 DOM 操作、第三方库初始化

5. beforeUpdate

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

  • 特点

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

    • 适合在更新前访问现有 DOM

6. updated

  • 调用时机:数据更改导致的虚拟 DOM 重新渲染和打补丁之后

  • 特点

    • 可以访问更新后的 DOM

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

7. beforeUnmount (Vue 3) / beforeDestroy (Vue 2)

  • 调用时机:实例销毁之前

  • 特点

    • 实例仍然完全可用

    • 适合清理定时器、取消订阅等

8. unmounted (Vue 3) / destroyed (Vue 2)

  • 调用时机:实例销毁后

  • 特点

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

    • 所有子实例也已销毁

实际示例演示

下面是一个完整的示例,展示各个生命周期阶段的执行顺序和 data 的可访问性:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vue 生命周期详解</title><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script><style>body {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;line-height: 1.6;color: #333;max-width: 1000px;margin: 0 auto;padding: 20px;background-color: #f5f7fa;}.container {display: flex;gap: 20px;margin-top: 20px;}.lifecycle-explanation {flex: 1;background: white;padding: 20px;border-radius: 8px;box-shadow: 0 2px 10px rgba(0,0,0,0.1);}.demo-component {flex: 1;background: white;padding: 20px;border-radius: 8px;box-shadow: 0 2px 10px rgba(0,0,0,0.1);}h1 {color: #2c3e50;border-bottom: 2px solid #42b883;padding-bottom: 10px;}h2 {color: #42b883;}.phase {margin: 15px 0;padding: 10px;border-left: 4px solid #42b883;background-color: #f8f9fa;}.phase h3 {margin-top: 0;color: #2c3e50;}.log-container {background: #2c3e50;color: #42b883;padding: 15px;border-radius: 5px;height: 300px;overflow-y: auto;font-family: 'Courier New', monospace;margin-top: 15px;}button {background: #42b883;color: white;border: none;padding: 8px 15px;border-radius: 4px;cursor: pointer;margin: 5px;}button:hover {background: #3aa876;}.data-access {background: #e8f5e9;padding: 10px;border-radius: 4px;margin: 10px 0;}.highlight {background-color: #fff3cd;padding: 10px;border-radius: 4px;border-left: 4px solid #ffc107;}</style>
</head>
<body><div id="app"><h1>Vue 生命周期详解</h1><div class="container"><div class="lifecycle-explanation"><h2>生命周期阶段</h2><div class="phase"><h3>创建阶段</h3><p><strong>beforeCreate</strong> - 实例初始化后,数据观测和事件配置之前</p><p><strong>created</strong> - <span class="highlight">可以首次访问 data</span>,但尚未挂载到 DOM</p><p><strong>beforeMount</strong> - 挂载开始之前,模板编译完成</p><p><strong>mounted</strong> - 实例已挂载到 DOM,<span class="highlight">可以访问 DOM 元素</span></p></div><div class="phase"><h3>更新阶段</h3><p><strong>beforeUpdate</strong> - 数据更新时,DOM 重新渲染前</p><p><strong>updated</strong> - 数据更新后,DOM 已重新渲染</p></div><div class="phase"><h3>卸载阶段</h3><p><strong>beforeUnmount</strong> - 实例销毁之前</p><p><strong>unmounted</strong> - 实例销毁后</p></div><div class="data-access"><h3>数据访问时机</h3><p><strong>✅ created 及之后</strong> - 可以访问 data、computed、methods</p><p><strong>✅ mounted 及之后</strong> - 可以访问 DOM 元素</p><p><strong>❌ beforeCreate</strong> - 无法访问 data</p></div></div><div class="demo-component"><h2>生命周期演示</h2><p>计数器: {{ count }}</p><button @click="increment">增加计数</button><button @click="reset">重置</button><button @click="toggleComponent" v-if="showComponent">卸载组件</button><button @click="toggleComponent" v-else>加载组件</button><div class="log-container"><div v-for="log in logs" :key="log.id">{{ log.message }}</div></div></div></div></div><script>const { createApp } = Vue;// 子组件定义const LifecycleDemo = {name: 'LifecycleDemo',template: `<div style="border: 1px solid #42b883; padding: 10px; margin: 10px 0;"><h3>子组件</h3><p>子组件计数: {{ childCount }}</p><button @click="childCount++">子组件计数+1</button></div>`,data() {return {childCount: 0}},beforeCreate() {this.$parent.logLifecycle('子组件 - beforeCreate', 'childCount: ' + (typeof this.childCount));},created() {this.$parent.logLifecycle('子组件 - created', 'childCount: ' + this.childCount);},beforeMount() {this.$parent.logLifecycle('子组件 - beforeMount');},mounted() {this.$parent.logLifecycle('子组件 - mounted');},beforeUpdate() {this.$parent.logLifecycle('子组件 - beforeUpdate', 'childCount: ' + this.childCount);},updated() {this.$parent.logLifecycle('子组件 - updated');},beforeUnmount() {this.$parent.logLifecycle('子组件 - beforeUnmount');},unmounted() {this.$parent.logLifecycle('子组件 - unmounted');}};// 主应用const app = createApp({data() {return {count: 0,logs: [],logId: 0,showComponent: true}},components: {LifecycleDemo},methods: {logLifecycle(hook, extra = '') {const message = `[${new Date().toLocaleTimeString()}] ${hook} ${extra}`;this.logs.push({ id: this.logId++, message });// 保持日志区域滚动到底部this.$nextTick(() => {const logContainer = this.$el.querySelector('.log-container');if (logContainer) {logContainer.scrollTop = logContainer.scrollHeight;}});},increment() {this.count++;},reset() {this.count = 0;this.logs = [];this.logId = 0;},toggleComponent() {this.showComponent = !this.showComponent;}},beforeCreate() {// 此时无法访问 datathis.logLifecycle('父组件 - beforeCreate', `count: ${typeof this.count} (此时无法访问data)`);},created() {// 此时可以访问 datathis.logLifecycle('父组件 - created', `count: ${this.count} (此时可以访问data)`);},beforeMount() {this.logLifecycle('父组件 - beforeMount');},mounted() {this.logLifecycle('父组件 - mounted');},beforeUpdate() {this.logLifecycle('父组件 - beforeUpdate', `count: ${this.count}`);},updated() {this.logLifecycle('父组件 - updated');},beforeUnmount() {this.logLifecycle('父组件 - beforeUnmount');},unmounted() {this.logLifecycle('父组件 - unmounted');}});app.mount('#app');</script>
</body>
</html>

关键要点总结

  1. created 阶段:首次可以访问 data、computed、methods 等响应式数据

  2. mounted 阶段:首次可以访问 DOM 元素,适合进行 DOM 操作

  3. 更新阶段:数据变化时触发,用于响应数据变化

  4. 卸载阶段:用于清理工作,如取消事件监听、清除定时器等

这个示例直观地展示了 Vue 生命周期的各个阶段,特别是清晰地标明了何时可以访问 data 数据。你可以通过操作界面上的按钮来触发不同生命周期阶段,观察控制台输出的日志信息。

http://www.dtcms.com/a/515527.html

相关文章:

  • vue3调用ant-design-vue组件库的a-table组件
  • 手机网站开发软件南昌网站外包
  • 以图搜图随州网站seo诊断
  • java设计模式六、装饰器模式
  • 微信小程序隐藏滚动条多种方法教程
  • AWS DMS实现MySQL到Redshift的CDC增量数据复制方案
  • 王者重名生成查询抖音快手微信小程序看广告流量主开源
  • 旅游网站建设1000字软文范例800字
  • 网站搜索引擎友好性最近三天发生的重要新闻
  • Flink的checkpoint interval与mini-batch什么区别?
  • CADSoftTools发布两款重要更新:CAD VCL Multiplatform 16.2 与 CAD .NET 16全新发布
  • 【个人成长笔记】在本地Windows系统中如何正确使用adb pull命令,把Linux系统中的文件或文件夹复制到本地中(亲测有效)
  • 触摸未来2025-10-22:语序之困
  • 【滑动窗口与双指针】【定长滑窗】—1456. 定长子串中元音的最大数目
  • Flink 实验性特性把“已预分区”的 DataStream 重新解释为 KeyedStream
  • ADB -> 常用文件操作的组合命令
  • 网格系统网站济南网约车公司
  • 社区网站的推广方案手机写wordpress博客
  • 原子性、可见性和指令重排问题的根源
  • 什么是测试覆盖率?如何衡量?
  • 《宝可梦传说Z-A》下载 整合龙神Ryuinx、eden模拟器附金手指和存档 安卓手机PC版
  • 自动驾驶---基于安全走廊的端到端
  • 2025主流AI标书工具推荐,“闭眼选”高效生成投标文件
  • (22)100天python从入门到拿捏《【网络爬虫】网络基础与HTTP协议》
  • iis6建设网站叶梓 wordpress 主题
  • 【C#】获取电脑网卡MAC地址
  • ​2025网络安全前景与学习路线:抓住数字时代的安全机遇
  • Linux小课堂: SSH 服务部署与客户端连接实战详解
  • 好看网站手机版南开做网站公司
  • 七日 Go 的自学笔记 (一)