【Vue3源码Runtime-core篇】 第一章 初识Runtime

news/2024/10/29 2:40:09/

第一章 初识Runtime

前言

当设计一个框架的时候,我们有三种选择:纯运行时的、运行时 + 编译时的或纯编译时的。
我们先聊聊纯运行时的框架。
假设我们设计了一个框架,它提供 一个 Render 函数,用户可以为该函数提供一个树型结构的数据对象,然后 Render 函数会根据该对象递归地将数据渲染成 DOM 元素。我们规定树型结构的数据对象如下:

const obj = {tag: 'div',children: [{ tag: 'span', children: 'hello world' }]}

每个对象都有两个属性:tag 代表标签名称,children 既可以是一个数组(代表子节点),也可以直接是一段文本(代表文本子节点)。接着,我们来实现 Render 函数:

function Render(obj, root) {const el = document.createElement(obj.tag)if (typeof obj.children === 'string') {const text = document.createTextNode(obj.children)el.appendChild(text)} else if (obj.children) {// 数组,递归调用 Render,使用 el 作为 root 参数obj.children.forEach((child) => Render(child, el))}// 将元素添加到 rootroot.appendChild(el)}const obj = {tag: 'div',children: [{ tag: 'span', children: 'hello world' }]}// 渲染到 body 下Render(obj, document.body)

在浏览器中运行上面这段代码,就可以看到我们预期的内容。
现在我们回过头来思考一下用户是如何使用 Render 函数的。可以发现,用户在使用它渲染内容时,直接为Render 函数提供了一个树型结构的数据对象。这里面不涉及任何额外的步骤用户也不需要学习额外的知识。但是有一天,你的用户抱怨说:“手写树型结构的数据对象太麻烦了,而且不直观,能不能支持用类似于 HTML 标签的方式描述树型结构的数据对象呢?”你看了看现在的 Render 函数,然后回答:“抱歉,暂不支持。”实际上,我们刚刚编写的框架就是一个纯运行时的框架。

以上摘自《Vue3设计与实现》

根据上文再结合之前我们已经学习的@vue/reactivity包,对Vue响应式的原理有了深刻理解,那么这些副作用函数响应式数据到底是怎么在Vue中自动化渲染的呢?

答案: 就是接下来要学习的@vue/runtime-core包

学习完这个包之后,我们就会对 Vue 的挂载和更新有更加深刻的理解。
接下来还会涉及到Vue3中的虚拟节点diff算法、组件化、nextTick等重要知识点。

好了那么开始源码学习吧~

runtime-core模块

runtime-core的核心流程主要对是render函数的调用。在render函数中最重要的就是两个算法:patch算法diff算法

patch算法: 会遍历所有VNode虚拟节点,根据节点类型去运行相应的渲染操作,然后把虚拟节点一一渲染挂载到根节点上。
diff 算法: 会去对比新老虚拟DOM树,通过双端对比过滤出中间乱序部分,对乱序部分使用最长递增子序列算法求得最长递增的新DOM树,根据这个递增的新DOM树为基础,在其基础上 添加和移动 DOM树中其他乱序节点。

后续章节讲到diff算法时,会画图做演示,方便大家理解!

VNode

VNode 就是我们常说的虚拟 DOM 对象
那么我们怎么创建VNode呢?
createVNode 函数就是用来创建虚拟 DOM 节点的辅助函数, 它的基本实现类似于:

 function createVNode(tag, props, children) {const key = props && props.keyprops && delete props.keyreturn {tag,props,children,key}}

他最主要包括type,props,children三部分

举个例子:
vue模板中这段HTML结构

<div id="foo"><p class="bar">{{ text }}</p>
</div>

最后会被编译成

render() {return createVNode('div', { id: 'foo' }, [createVNode('p', { class: 'bar' }, text, PatchFlags.TEXT) //PatchFlags.TEXT 就是补丁标志])
}

PatchFlags.TEXT 就是补丁标志
这个标志很重要,它会在patch算法中被识别并进入相应的初始化阶段

那么生成了虚拟dom对象后,我们就可以进入下一步,patch算法环节了。

patch算法

首先我们先看下源码中的runtime-core文件夹下renderer.ts文件找到patch函数。
其实patch算法内部就是判断我们生成好的VNode的类型,然后根据类型去做一些渲染初始化操作

渲染一般分3步:创建元素节点添加元素属性挂载到对应的节点上

在这里插入图片描述

可以看到源码判断了很多种情况,包括Text、Static等类型和SUSPENSE、TELEPORT、Fragment等组件

上文提到patch算法通过判断VNode的类型进行不同的渲染逻辑
我们刚起步,所以主要重点讲一讲runtime-core初始化ElementComponent的这两种类型,它们两对应processElementprocessComponent两个初始化函数,那么这两个函数运行逻辑是怎么样呢?
我们看一下patch算法在识别ElementComponent运行过程的流程图:
在这里插入图片描述

了解了patch算法运行的流程图之后,下一章节我们就可以正式的开始,初始化Component逻辑了,也就是源码中的processComponent(vnode, container)函数。


http://www.ppmy.cn/news/37447.html

相关文章

33、搜索旋转排序数组

难度&#xff1a;中等 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], n…

RocketMQ中核心概念及术语介绍

文章目录 角色ProducerConsumerPushConsumerPullConsumer概念术语Producer GroupConsumer GroupTopicTagMessage QueueOffsetConsumer Offset集群消费广播消费顺序消息普通顺序消息严格顺序消息RocketMQ中有很多独有的概念,其中包括一些术语和角色。 理清楚基本的概念是理解原…

前端重装系统需要安装什么

目录 1.安装nvm 2.安装git 3.安装yarn 4. 安装cnpm 5. 配置hbuilder 6. 配置vscode 1.安装nvm 1.1 下载 下载地址&#xff1a;Releases coreybutler/nvm-windows GitHub 如果下载慢&#xff0c;可以复制链接到迅雷下载 1.2 安装 在c盘下创建一个nvm文件夹并创建一个…

【蓝桥杯集训·每日一题】 AcWing 3996. 涂色

文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴区间DPUnique函数一、题目 1、原题链接 3996. 涂色 2、题目描述 有 n 个砖块排成一排&#xff0c;从左到右编号为 1∼n。 其中&#xff0c;第 i 个砖块的初始颜色为 ci。 …

一键部署自己的ChatGPT!

昨晚咱们群友推荐了一个叫做ChatGPT-Next-Web项目&#xff0c;可以一键免费部署你的私人 ChatGPT 网页应用。今早起来尝试了下&#xff0c;整体过程非常丝滑&#xff0c;觉得有必要推荐给大家。项目整体是基于Vercel平台开发的&#xff0c;只要提供api key&#xff0c;即可在1分…

xijs更新指南(v1.2.1)

xijs 是一款开箱即用的 js 业务工具库, 聚集于解决业务中遇到的常用函数逻辑问题, 帮助开发者更高效的开展业务开发.接下来就和大家一起分享一下v1.2.1 版本的更新内容以及后续的更新方向.1. 添加算法模块分类该模块主要由 WangLei802 贡献, 添加内容如下:添加冒泡排序算法及其…

开发了一个抠图/去背景应用

jr们早上好 iPhone 的 iOS 16有个很酷的功能&#xff0c;长按照片就能把其中的拍摄主体提取出来&#xff0c;抠图过程比一般的抠图App方便&#xff0c;精细度也更高。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KIlpLyow-1680141413142)(https…

【面试题】面试官:请你说说对Vue响应式数据的理解

前言 我们平时的面试过程当中&#xff0c;问到Vue&#xff0c;几乎都会问到响应式的问题&#xff0c;因为在Vue的实现当中&#xff0c;响应式系统的实现就占据很大一个篇幅。这是Vue声明式编程的基石。那么如何理解响应式数据呢&#xff1f;相信结合源码以及手写实现会有一个更…