vue3生命周期源码详解

news2024/11/26 4:55:23

在这里插入图片描述

钩子函数的特点

Vue 生命周期钩子函数是在组件生命周期中执行的特定函数。

这些钩子函数允许你在组件不同的生命周期阶段插入自定义的逻辑代码。

Vue 提供了一组预定义的生命周期钩子函数,每个钩子函数在组件生命周期的不同阶段被调用。

源码中如何注册、实现钩子函数?

代码示例

const onBeforeMount = createHook('bm' /* BEFORE_MOUNT */)
const onMounted = createHook('m' /* MOUNTED */)
const onBeforeUpdate = createHook('bu' /* BEFORE_UPDATE */)
const onUpdated = createHook('u' /* UPDATED */)
const onBeforeUnmount = createHook('bum' /* BEFORE_UNMOUNT */)
const onUnmounted = createHook('um' /* UNMOUNTED */)
const onRenderTriggered = createHook('rtg' /* RENDER_TRIGGERED */)
const onRenderTracked = createHook('rtc' /* RENDER_TRACKED */)
const onErrorCaptured = (hook, target = currentInstance) => {
  injectHook('ec' /* ERROR_CAPTURED */, hook, target)
}

除去onErrorCaptured其他的钩子函数都是直接调用createHook。

createHook方法源码解析

createHook对injectHook进行封装。

 const createHook = function(lifecycle)  {
  return function (hook, target = currentInstance) {
    injectHook(lifecycle, hook, target)
  }
}

柯里化的封装过程带来的优势

  1. 提高函数的复用性:可以将原本接收多个参数的函数转变为接收部分参数的函数。这样,我们可以复用具有相同生命周期的钩子函数的逻辑,只需传入不同的目标实例即可。这种封装方式使得代码更加灵活,易于扩展和维护。

  2. 简化函数调用:可以将原本需要在调用时传递的参数提前传入并固定,从而简化函数调用。在这个例子中,createHook 函数返回的函数只需要传递 hook 和可选的 target 参数即可,无需再重复传递 lifecycle 参数。

  3. 隐藏实现细节:可以隐藏一些实现细节,使得函数调用更加简洁,同时也减少了外部对内部函数的直接访问。这种封装方式可以提高代码的可维护性和安全性

injectHook方法源码解析

function injectHook(type, hook, target = currentInstance, prepend = false) {
  // 从目标组件实例中获取相应的钩子函数数组
  const hooks = target[type] || (target[type] = [])
  // 封装传入的钩子函数,用于添加实例检查、错误处理等逻辑
  const wrappedHook = hook.__weh || 
    (hook.__weh = (...args) => {
      // 检查目标组件是否已卸载
      if (target.isUnmounted) {
        return
      }
      // 停止依赖收集,避免执行钩子时产生副作用
      pauseTracking()
      // 设置当前运行组件实例为目标实例  
      setCurrentInstance(target)
      // 调用传入的钩子函数
      const res = callWithAsyncErrorHandling(hook, target, type, args)
      // 重置当前组件实例
      setCurrentInstance(null)
      // 恢复依赖收集
      resetTracking()
      return res
    })
  // 根据传入的参数将封装后的钩子推入数组前或后
  if (prepend) {
    hooks.unshift(wrappedHook) 
  } else {
    hooks.push(wrappedHook)
  }
}

这样的设计非常易于理解,因为生命周期的钩子函数在组件的不同阶段执行,所以这些钩子函数需要保存在当前组件实例上。

这样,后续就可以通过不同的字符串键查找对应的钩子函数数组,并执行相应的逻辑。

举例onBeforeMount 和 onMounted

onBeforeMount 注册的 beforeMount 钩子函数会在组件挂载之前执行,onMounted 注册的 mounted钩子函数会在组件挂载之后执行。

const setupRenderEffect = (instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized) => {
  // 创建响应式的副作用渲染函数
  instance.update = effect(function componentEffect() { 
    if (!instance.isMounted) {
      // 获取组件注册的钩子函数
      const { bm, m } = instance;
      // 渲染组件生成子树vnode
      const subTree = (instance.subTree = renderComponentRoot(instance))
      // 执行beforeMount钩子函数
      if (bm) {
        invokeArrayFns(bm) 
      }
      // 将子树vnode挂载到container上
      patch(null, subTree, container, anchor, instance, parentSuspense, isSVG)
      // 保留渲染生成的子树根DOM节点
      initialVNode.el = subTree.el;
      // 执行mounted钩子函数  
      if (m) {
        queuePostRenderEffect(m, parentSuspense)
      }
      // 标记已挂载
      instance.isMounted = true;
    } else {
      // 更新组件
    }
  }, prodEffectOptions)
} 

在执行组件挂载之前,会检测组件实例上是否存在注册的 beforeMount 钩子函数(bm)。
如果存在,通过遍历 instance.bm数组并使用 invokeArrayFns 方法依次执行这些钩子函数。
这样设计的原因是用户可以通过多次调用 onBeforeMount函数来注册多个 beforeMount 钩子函数,保证它们按注册顺序依次执行。

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

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

相关文章

cad绘图模板建立

都设置好后保存为文件,收藏好,下次打开即可使用设置好的样式,完成后另存为新的文件名即可 1.f7关闭格栅 2.ds草图设置 3.图纸不能缩小:格式——图形界限—— 4.un单位设置 5.标注样式设置:d 完成后置为当前 6. st…

docker存储卷

docker存储卷 COW机制 Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。 如果运行中的容器修改了现有的一个已经存在的 文件,那么该文件将会从读写层下面的只读层复制到读写层&#xff0…

5米DEM高程数据分析和对比

数字高程模型(DEM)是应用最广泛的地理信息数据之一,是进行三维空间处理和地形分析的数据基础。每个行业数据精度要求不一样,很多行业使用公开免费的90米和30米分辨率DEM就够了。而城市规划、交通线路规划、地质灾害防控、城区地籍…

【QT】 Qt自定义ui控件

在使用Qt的ui设计时,Qt为我们提供了标准的窗口控件,但是在很多复杂工程中,标准窗口控件并不能满足所有的需求,这时就需要我们自定义控件。我们自定义的类既可以作为独立的窗口显示,又可以作为一个控件显示。 我们要实现…

Spring相关

SpringBoot自动装配 阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台 Spring相关 阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台 常用设计模式 双亲委派 Java虚拟机定义了三个主要的类加载器: 1、启动类加载器 2、扩展类加载器 …

python教程:打印心型图案 九九乘法表 三角形 金字塔 圣诞树 倒三角形 菱形

# 打印九九乘法口诀表 for i in range(1, 10): # 乘法表的行、起始值从1开始for j in range(1, i 1): # 表示每一行的表达式、从1开始、到j1print({}*{}{}.format(j, i, i * j), end ) # 输出语句{}占位、输出表达式print( )# 打印金字塔(正三角形) …

web3 dapp React项目引入 antd 对 balance 用户token信息组件进行样式改造

好 上文 web3 React dapp中编写balance组件从redux取出并展示用户资产 我们简单处理了用户资产的展示 那么 我们继续 先启动 ganache 环境 终端输入 ganache -d然后 打开我们的项目 将合约发布到区块链上 truffle migrate --reset然后 我们启动项目 确认一切正常 还原到上文…

wangeditor富文本编辑器的使用(vue)

官网 官方demo 参考 安装 yarn add wangeditor/editor yarn add wangeditor/editor-for-vue 封装的富文本组件 <template><div style"border: 1px solid #ccc"><Toolbarstyle"border-bottom: 1px solid #ccc":editor"editorRef"…

P02项目(学习)

★ P02项目 项目描述&#xff1a;安全操作项目旨在提高医疗设备的安全性&#xff0c;特别是在医生离开操作屏幕时&#xff0c;以减少非授权人员的误操作风险。为实现这一目标&#xff0c;我们采用多层次的保护措施&#xff0c;包括人脸识别、姿势检测以及二维码识别等技术。这些…

工程压缩与解压缩

很多工程师在完成一个电气工程后&#xff0c;会遇到一些问题&#xff0c;例如&#xff1a;在SOLIDWORKSElectrical 中如何把做好的工程发送给别的工程师&#xff0c;或者更换了电脑如何把旧电脑的工程转移到新电脑 上&#xff1b;有时候&#xff0c;工程师也有可能会遇到解压工…

Redis概述和安装

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349; 本篇详细阐述了Redis概述和安装&#xff0c;如有出入…

经典OJ题:找环节点——代码解析

题目&#xff1a; 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测…

【每日一题】统计范围内的元音字符串数

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;遍历 其他语言python3 写在最后 Tag 【遍历】【数组】【2023-11-07】 题目来源 2586. 统计范围内的元音字符串数 题目解读 统计范围内的元音字符串数。 解题思路 方法一&#xff1a;遍历 遍历下标在 [left, right]…

用循环结构程序自动化计算——计数循环

用循环结构程序自动化计算——计数循环 低阶目标&#xff1a; 利用for循环结构来完成已知次数的自动化处理&#xff0c;掌握计数循环结构应用方法 高阶目标&#xff1a; 学会利用for循环解决生活中的实际问题 用循环结构程序自动化计算——计数循环 用循环结构程序自动化计算…

Leetcode48旋转图像

思路&#xff1a;找规律 方法一、一般辅助数组解法 行列转换&#xff0c;第一行变到第三列&#xff0c;第二行变到第二列&#xff0c;第三行变到第一列 matrix[row][col] matrix[col][n-row-1] 然后复制回原数组 class Solution {public void rotate(int[][] matrix) {in…

第十二章 Python正则表达式

系列文章目录 第一章 Python 基础知识 第二章 python 字符串处理 第三章 python 数据类型 第四章 python 运算符与流程控制 第五章 python 文件操作 第六章 python 函数 第七章 python 常用内建函数 第八章 python 类(面向对象编程) 第九章 python 异常处理 第十章 python 自定…

独立键盘接口设计(Keil+Proteus)

前言 软件的操作参考这篇博客。 LED数码管的静态显示与动态显示&#xff08;KeilProteus&#xff09;-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/134101256?spm1001.2014.3001.5501实验&#xff1a;用4个独立按键控制8个LED指示灯。 按下k1键&#x…

VB.NET—DataGridView控件教程详解

目录 前言: 过程: 第一步: 第二步: 第三步: 第四步: 第五步&#xff1a; 番外篇: 总结: 前言: DataGridView是.NET FormK中的一个Windows窗体控件&#xff0c;它提供了一个可视化的表格控件&#xff0c;允许用户以表格形式显示和编辑数据。它通常用于显示和编辑数据库…

50基于matlab的传统滤波、Butterworth滤波、FIR、移动平均滤波、中值滤波、现代滤波、维纳滤波、自适应滤波、小波变换

基于matlab的传统滤波、Butterworth滤波、FIR、移动平均滤波、中值滤波、现代滤波、维纳滤波、自适应滤波、小波变换&#xff0c;七种滤波方法&#xff0c;可替换自己的数据进行滤波&#xff0c;程序已调通&#xff0c;可直接运行。 50matlabButterworth滤波 (xiaohongshu.com)…

AI创作系统ChatGPT商业运营系统源码+支持GPT4/支持ai绘画

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…