Vue框架之钩子函数详解

Vue框架之生命周期主要钩子函数详解

    • 一、Vue生命周期的整体流程
    • 二、创建阶段:初始化组件实例
      • 2.1 `beforeCreate`:实例创建前
      • 2.2 `created`:实例创建后
    • 三、挂载阶段:组件与DOM结合
      • 3.1 `beforeMount`:挂载前
      • 3.2 `mounted`:挂载后
    • 四、更新阶段:数据变化触发重渲染
      • 4.1 `beforeUpdate`:更新前
      • 4.2 `updated`:更新后
    • 五、销毁阶段:组件实例的清理
      • 5.1 `beforeDestroy`:销毁前
      • 5.2 `destroyed`:销毁后
    • 六、特殊场景的钩子函数
      • 6.1 keep-alive 相关钩子
      • 6.2 错误捕获钩子:`errorCaptured`
    • 七、生命周期钩子的执行顺序与实战示例
      • 7.1 单组件执行顺序
      • 7.2 父子组件执行顺序
    • 八、常见问题与避坑指南
      • 8.1 避免在`updated`中修改数据
      • 8.2 子组件`mounted`晚于父组件`mounted`
      • 8.3 清理资源是重中之重
    • 九、Vue 3中的生命周期变化

Vue的生命周期是指组件从创建到销毁的整个过程,而生命周期钩子函数则是在这个过程中特定时间点自动执行的函数。掌握这些钩子函数,能让我们在合适的时机执行特定操作(如数据请求、DOM操作、资源清理等),是Vue开发的核心基础。

一、Vue生命周期的整体流程

Vue组件的生命周期可分为4个阶段,每个阶段包含若干钩子函数,整体流程如下:

  1. 创建阶段:组件实例从初始化到挂载前的过程
  2. 挂载阶段:组件实例挂载到DOM的过程
  3. 更新阶段:组件数据变化导致重新渲染的过程
  4. 销毁阶段:组件实例从DOM中移除并清理资源的过程

二、创建阶段:初始化组件实例

创建阶段是组件实例从无到有的过程,主要完成数据观测(响应式处理)、事件初始化等工作,此时尚未涉及DOM操作。

2.1 beforeCreate:实例创建前

  • 执行时机:Vue实例初始化后(new Vue()之后),数据观测(dataprops)和事件机制初始化前调用。
  • 特点
    • 无法访问datapropsmethods中的数据和方法(此时尚未初始化)。
    • 不能进行DOM操作(DOM尚未生成)。
  • 适用场景:极少使用,可用于初始化非响应式数据(如临时变量)。
new Vue({data() {return { message: 'Hello' };},beforeCreate() {console.log('beforeCreate:', this.message); // undefined(无法访问data)console.log('methods:', this.getMsg); // undefined(无法访问methods)},methods: {getMsg() { return this.message; }}
});

2.2 created:实例创建后

  • 执行时机:Vue实例初始化完成后调用,此时已完成dataprops的响应式处理和methods的绑定,但尚未开始DOM编译(模板未挂载到DOM)。
  • 特点
    • 可访问datapropsmethods中的数据和方法。
    • 仍无法进行DOM操作($el属性不存在,DOM未生成)。
  • 适用场景
    • 发起初始化数据请求(如获取列表数据)。
    • 初始化数据(如对data中的数据进行预处理)。
    • 绑定自定义事件。
new Vue({el: '#app',data() {return { list: [] };},created() {console.log('created:', this.list); // [](可访问data)console.log('$el:', this.$el); // undefined(DOM未挂载)// 示例:发起数据请求axios.get('/api/list').then(response => {this.list = response.data; // 数据响应后更新list(响应式)});}
});

三、挂载阶段:组件与DOM结合

挂载阶段是组件实例与DOM关联的过程,核心是将编译后的模板挂载到页面中,此时开始具备DOM操作能力。

3.1 beforeMount:挂载前

  • 执行时机:模板编译(解析指令、插值表达式等)完成后,DOM挂载到页面之前调用。
  • 特点
    • 已完成模板编译,生成虚拟DOM(但未渲染到页面)。
    • $el属性存在(指向即将挂载的DOM元素),但内容仍为原始模板(未替换数据)。
    • 仍无法操作DOM(数据未渲染,操作无意义)。
  • 适用场景:极少使用,可用于获取模板编译前的DOM结构。
new Vue({el: '#app',template: '<div>{{ message }}</div>',data() { return { message: '挂载前' }; },beforeMount() {console.log('beforeMount $el:', this.$el); // <div>{{ message }}</div>(未替换)console.log('页面内容:', document.getElementById('app').innerHTML); // 原始模板}
});

3.2 mounted:挂载后

  • 执行时机:模板挂载到DOM后调用,此时页面已显示渲染后的内容。
  • 特点
    • DOM已完全渲染,可通过$el或原生DOM API(如document.getElementById)操作DOM。
    • 子组件的mounted可能在父组件的mounted之后执行(因渲染顺序)。
  • 适用场景
    • 执行DOM操作(如初始化第三方UI插件:图表、地图等,需依赖DOM元素)。
    • 监听DOM事件(如滚动、resize)。
    • 若数据请求依赖DOM尺寸(如根据容器宽度请求不同数据),可在此发起请求。
new Vue({el: '#app',data() { return { width: 0 }; },mounted() {// 获取DOM元素宽度this.width = this.$el.offsetWidth;console.log('挂载后宽度:', this.width);// 初始化第三方图表插件(假设页面有<div id="chart"></div>)this.chart = new Chart(document.getElementById('chart'), {type: 'line',data: { labels: ['1月', '2月'], datasets: [{ data: [10, 20] }] }});// 监听滚动事件window.addEventListener('scroll', this.handleScroll);},methods: {handleScroll() { /* 处理滚动逻辑 */ }}
});

四、更新阶段:数据变化触发重渲染

当组件的dataprops发生变化时,会进入更新阶段,触发重新渲染,此阶段的钩子函数用于监控或干预更新过程。

4.1 beforeUpdate:更新前

  • 执行时机:数据发生变化后,虚拟DOM重新渲染前调用。
  • 特点
    • 此时data中的数据已更新,但DOM尚未重新渲染(页面显示旧数据)。
    • 可获取更新前的DOM状态。
  • 适用场景:获取更新前的DOM信息(如滚动位置、输入框光标位置),用于更新后恢复状态。
new Vue({el: '#app',data() { return { count: 0 }; },template: '<div>{{ count }} <button @click="count++">+1</button></div>',beforeUpdate() {console.log('更新前data:', this.count); // 新值(如1)console.log('更新前DOM:', this.$el.textContent); // 旧值(如0)}
});

4.2 updated:更新后

  • 执行时机:虚拟DOM重新渲染并更新到页面后调用,此时页面显示最新数据。
  • 特点
    • data和DOM均已更新,可获取最新的DOM状态。
    • 若在updated中修改data,会再次触发更新(可能导致无限循环,需避免)。
  • 适用场景
    • 基于最新DOM状态执行操作(如根据新内容调整元素样式)。
    • 同步第三方插件数据(如图表数据更新后,重新绘制图表)。
new Vue({el: '#app',data() { return { data: [10, 20] }; },template: '<div>{{ data }}</div>',updated() {console.log('更新后DOM:', this.$el.textContent); // 显示最新data// 若图表数据依赖this.data,更新后重新绘制if (this.chart) {this.chart.data.datasets[0].data = this.data;this.chart.update();}}
});

五、销毁阶段:组件实例的清理

当组件被销毁(如v-if="false"移除组件、路由切换)时,进入销毁阶段,此阶段的钩子函数用于清理资源,避免内存泄漏。

5.1 beforeDestroy:销毁前

  • 执行时机:组件实例销毁前调用,此时组件仍处于正常工作状态。
  • 特点
    • 可访问datamethods、DOM等所有资源。
    • 子组件的beforeDestroy会在父组件的beforeDestroy前执行。
  • 适用场景
    • 清理定时器、事件监听器(避免组件销毁后仍执行)。
    • 取消未完成的请求(避免资源浪费)。
    • 解绑自定义事件。
new Vue({el: '#app',data() {return { timer: null };},mounted() {// 启动定时器this.timer = setInterval(() => {console.log('定时器执行中...');}, 1000);// 绑定事件window.addEventListener('resize', this.handleResize);},beforeDestroy() {// 清理定时器clearInterval(this.timer);// 移除事件监听window.removeEventListener('resize', this.handleResize);// 取消未完成的请求(假设使用axios)if (this.source) {this.source.cancel('组件销毁,取消请求');}},methods: {handleResize() { /* 处理窗口大小变化 */ }}
});

5.2 destroyed:销毁后

  • 执行时机:组件实例销毁后调用,此时组件的所有资源已被释放。
  • 特点
    • 组件的响应式数据、事件监听、子组件等均已被销毁。
    • 仍可访问$el,但DOM可能已被移除(取决于销毁方式)。
  • 适用场景:极少使用,可用于最终的资源清理或日志记录。
new Vue({destroyed() {console.log('组件已销毁');// 记录销毁日志console.log('组件销毁时间:', new Date().toLocaleString());}
});

六、特殊场景的钩子函数

除上述核心钩子外,Vue还提供了针对特殊场景的钩子函数:

6.1 keep-alive 相关钩子

keep-alive用于缓存组件(避免频繁创建/销毁),搭配两个专属钩子:

  • activated:缓存的组件被激活(显示)时调用。
  • deactivated:缓存的组件被停用(隐藏)时调用。
<!-- 缓存组件 -->
<keep-alive><component :is="currentComponent"></component>
</keep-alive><script>
new Vue({data() { return { currentComponent: 'ComponentA' }; },components: {ComponentA: {template: '<div>组件A</div>',activated() {console.log('组件A被激活(从缓存中取出)');// 可在此恢复状态(如刷新数据)},deactivated() {console.log('组件A被停用(存入缓存)');// 可在此暂停操作(如暂停视频播放)}}}
});
</script>

6.2 错误捕获钩子:errorCaptured

用于捕获子组件抛出的错误(Vue 2.5+),返回false可阻止错误向上传播:

new Vue({errorCaptured(err, vm, info) {console.error('捕获子组件错误:', err, '组件:', vm, '信息:', info);// 返回false阻止错误冒泡到控制台return false;}
});

七、生命周期钩子的执行顺序与实战示例

7.1 单组件执行顺序

new Vue({// 创建阶段beforeCreate() { console.log('1. beforeCreate'); },created() { console.log('2. created'); },// 挂载阶段beforeMount() { console.log('3. beforeMount'); },mounted() { console.log('4. mounted'); },// 更新阶段(触发条件:修改data)beforeUpdate() { console.log('5. beforeUpdate'); },updated() { console.log('6. updated'); },// 销毁阶段(触发条件:调用$destroy()或v-if移除)beforeDestroy() { console.log('7. beforeDestroy'); },destroyed() { console.log('8. destroyed'); }
});

执行结果
初始化时:1→2→3→4
修改数据时:5→6
销毁时:7→8

7.2 父子组件执行顺序

父组件Parent和子组件Child的钩子执行顺序:

  1. beforeCreate → 父created → 父beforeMount
  2. beforeCreate → 子created → 子beforeMount → 子mounted
  3. mounted
  4. (更新时)父beforeUpdate → 子beforeUpdate → 子updated → 父updated
  5. (销毁时)父beforeDestroy → 子beforeDestroy → 子destroyed → 父destroyed

结论:父组件等待子组件完成后,才会完成自身对应的阶段。

八、常见问题与避坑指南

8.1 避免在updated中修改数据

// 错误示例:导致无限循环
updated() {this.count++; // 修改data触发更新,再次调用updated,循环往复
}

解决方案:若需根据更新后的数据调整状态,可使用$nextTick或条件判断限制执行次数。

8.2 子组件mounted晚于父组件mounted

父组件若需等待子组件挂载完成后执行操作(如获取子组件DOM),需使用$nextTick或在子组件中通过事件通知父组件:

// 子组件
export default {mounted() {this.$emit('mounted'); // 通知父组件已挂载}
};// 父组件
<child-component @mounted="handleChildMounted"></child-component>
methods: {handleChildMounted() {console.log('子组件已挂载');}
}

8.3 清理资源是重中之重

组件销毁时若未清理定时器、事件监听等,会导致内存泄漏(页面关闭前资源一直占用):

// 错误:未清理定时器
mounted() {setInterval(() => { /* 操作 */ }, 1000); // 组件销毁后仍会执行
}// 正确:在beforeDestroy中清理
beforeDestroy() {clearInterval(this.timer);
}

九、Vue 3中的生命周期变化

Vue 3的Composition API中,生命周期钩子的使用方式有所调整,但核心逻辑一致:

  • setup():替代beforeCreatecreated(在两者之间执行)。
  • onBeforeMount:对应beforeMount
  • onMounted:对应mounted
  • onBeforeUpdate:对应beforeUpdate
  • onUpdated:对应updated
  • onBeforeUnmount:对应beforeDestroy
  • onUnmounted:对应destroyed
// Vue 3 Composition API示例
import { onMounted, onBeforeUnmount } from 'vue';export default {setup() {let timer;onMounted(() => {timer = setInterval(() => { /* 操作 */ }, 1000);});onBeforeUnmount(() => {clearInterval(timer); // 清理资源});}
};

总结

  1. 精准控制流程:在合适的阶段执行合适的操作(如created请求数据、mounted操作DOM)。
  2. 避免常见问题:如更新阶段的死循环、销毁阶段的内存泄漏。
  3. 优化组件性能:合理利用keep-alive和缓存钩子,减少不必要的创建/销毁。

若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/88776.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/88776.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Syntax Error: TypeError: Cannot set properties of undefined (setting ‘parent‘)

Date: 2025-07-12 19:21:24 author: lijianzhan使用npm run dev运行前端项目时报错&#xff0c;具体报错信息如下&#xff1a; ERROR Failed to compile with 1 error …

JAVA后端开发——类命名规范

引言良好的命名规范是软件工程的基石。它不仅能提升代码的可读性&#xff0c;还能降低团队协作的沟通成本&#xff0c;使项目在长期迭代中更易于维护。本规范结合了业界主流实践&#xff08;如阿里巴巴Java开发手册&#xff09;以及现代Web应用分层架构的特点&#xff0c;旨在提…

Ubuntu2404修改国内镜像

文章目录1 备份原文件2 修改文件内容Ubuntu2404修改国内镜像 2404和2204修改镜像的方式不一致 且镜像保存的位置也不一致&#xff0c;位置在/etc/apt/source.list.d/ubuntu.sources 参考&#xff1a;https://blog.csdn.net/Kiffy_Yam/article/details/145876447 1 备份原文件…

Chrome拓展 Video Speed Controller 等内嵌恶意后门

【高危】Chrome拓展 Video Speed Controller 等内嵌恶意后门 漏洞描述 当用户安装受影响版本的 Video Speed Controller 等Chrome拓展会窃取用户的浏览链接&#xff0c;并与攻击者可控的C2地址建立持久化连接&#xff0c;攻击者可将用户浏览器重定向到恶意网站。 MPS编号MPS…

Spring Ai Alibaba Gateway 实现存量应用转 MCP 工具

作者简介&#xff1a;你好&#xff0c;我是影子&#xff0c;Spring Ai Alibaba开源社区 Committer&#xff0c;持续分享Spring Ai Alibaba最新进展 业界各类AI工程相关的方案 最近有断时间没更了&#xff0c;熟悉我的朋友知道我刚结束完毕业旅行&#xff0c;最近也因为入职&a…

HTTP和HTTPS部分知识点

HTTP基本概念 超文本-传输-协议 协议 HTTP是一个用在计算机世界里的协议。它使用计算机可以理解的语言确立了一种计算机之间交流通信的规范(两个以上的参与者)&#xff0c;以及相关的各种控制和错误处理方式(行为约定和规范)。传输 HTTP协议是一个双向协议。是一个在计算机世界…

第10讲——一元函数积分学的几何应用

文章目录定积分计算平面图形的面积直角坐标系下参数方程下极坐标系下定积分计算旋转体的体积曲边梯形绕x轴旋转一周所得到的旋转体的体积曲边梯形绕y轴旋转一周所得到的旋转体的体积平面曲线绕定直线旋转定积分计算函数的平均值定积分计算平面光滑曲线的弧长曲线L绕x轴旋转一周…

Go从入门到精通(20)-一个简单web项目-服务搭建

Go从入门到精通&#xff08;15&#xff09;-包&#xff08;package&#xff09; Go从入门到精通&#xff08;9&#xff09;-函数 文章目录Go从入门到精通&#xff08;15&#xff09;-包&#xff08;package&#xff09;Go从入门到精通&#xff08;9&#xff09;-函数前言gogin…

Python爬虫实战:研究python-docx库相关技术

1. 引言 1.1 研究背景与意义 随着学术资源数字化程度的提高,科研工作者面临海量文献数据的筛选与分析挑战。传统人工调研方式效率低下,难以全面捕捉研究领域的动态趋势。自动化文献分析系统能够通过爬虫技术快速采集多源数据,并通过文本挖掘提取关键信息,为研究方向选择、…

Django中序列化与反序列化

1&#xff1a;序列化&#xff1a;将数据结构或对象状态转换为可以存储或传输的格式&#xff08;如JSON、XML&#xff09;的过程。在Web开发中&#xff0c;通常是将模型实例&#xff08;或查询集&#xff09;转换为JSON格式&#xff0c;以便通过HTTP响应发送给客户端。序列化&am…

【离线数仓项目】——电商域DWD层开发实战

摘要本文主要介绍了离线数仓项目中电商域DWD层的开发实战。DWD层是数据仓库架构中的明细数据层&#xff0c;对ODS层的原始数据进行清洗、规范、整合与业务建模。它具有数据清洗、标准化、业务建模、整合、维度挂载等作用&#xff0c;常见设计特征包括一致性、明细级建模、保留历…

爬虫-正则使用

1.模块选择用re模块导入&#xff0c;&#xff0c;最前面加个r&#xff0c;就不用怕转义了2.模块使用re.findall使用结果是数组方式呈现re.finditer把结果变成迭代器&#xff0c;从迭代器类中间取数re.searchre.search 只能匹配到第一个识别到的内容re.match3.推荐写法先预加载完…

python-range函数

文章目录基本用法重要特性与列表转换注意事项遍历回去列表的元素索引range()是Python中用于生成数字序列的内置函数&#xff0c;常用于循环和序列生成。基本用法 range(stop) # 生成0到stop-1的整数序列 range(start, stop) # 生成start到stop-1的整数序列 r…

汽车功能安全-软件集成和验证(Software Integration Verification)【目的、验证输入、集成验证要求】9

文章目录1 目的2 验证输入3 软件集成要求3.1 要求和建议3.2 汽车行业示例&#xff08;混合动力控制器软件&#xff09;4 验证要求1 目的 软件集成和验证阶段的核心目标是证明集成后的软件单元&#xff08;模块、组件&#xff09;已经正确地开发出来&#xff0c;满足了所有的功…

每天一个前端小知识 Day 27 - WebGL / WebGPU 数据可视化引擎设计与实践

WebGL / WebGPU 数据可视化引擎设计与实践&#x1f3af; 一、为什么前端需要 WebGL / WebGPU&#xff1f; 传统的图表库如 ECharts、Highcharts 基于 Canvas 或 SVG&#xff0c;适合 2D 渲染&#xff0c;但&#xff1a; 当数据量 > 1 万时&#xff0c;SVG 性能瓶颈明显&…

JavaScript代码段注入:动态抓取DOM元素的原理与实践

1.F12打开网页说明&#xff1a;以百度网站为例。通过插入代码块抓取当前网页dom元素。2.新代码段说明&#xff1a;点击源代码/来源菜单项下面的代码段。点击新代码段新增代码段。下面以脚本代码段#6为例。3.编写代码块说明&#xff1a;编写javascript代码&#xff0c;点击下面的…

Spring Easy

Spring Easy 用途 通过自动配置&#xff0c;实现了一些国内 Spring Boot 开发时需要在 Spring Boot 框架基础上完成的一些配置工作&#xff0c;可以提升基于 Spring Boot 开发 Web 应用的效率。 安装 使用 Maven 进行包管理&#xff0c;可以从中央仓库安装依赖&#xff1a;…

【Node.js】文本与 pdf 的相互转换

pdf 转文本 主要使用 pdf-parse 这个库&#xff0c;直接识别提取我们 pdf 文件中的文字。 const express require("express"); const fs require("fs"); const PDFParser require("pdf-parse"); const cors require("cors");const…

分布式ID方案

目录 &#x1f4ca; 分布式ID方案核心指标对比 &#x1f50d; 分方案深度解析 ⚙️ 1. UUID (Universally Unique Identifier) ❄️ 2. Snowflake (Twitter开源) ☘️ 3. 美团Leaf 号段模式 Snowflake模式 &#x1f504; 4. 百度UidGenerator &#x1f680; 5. CosId …

张量类型转换

一.前言本章节我们来讲解张量的类型转换&#xff0c;掌握张量的转换方法&#xff0c;张量的类型转换也是经常使⽤的⼀种操作&#xff0c;是必须掌握的知识点。在本⼩节&#xff0c;我们主要学习如何将 numpy 数组和 PyTorch Tensor 的转化⽅法.二.张量转换为 numpy 数组使⽤ Te…