vue 历程记

目录

  • 前言
  • 一、源码优化
    • 1、vue3.x 采用 monorep 的理念来管理源码
    • 2、vue3.x 源码采用 TypeScript 开发
  • 二、性能优化
    • 1、减少源码的体积
    • 2、数据劫持优化
    • 3、编译优化
      • (1)、编译粒度的优化
  • 三、语法 API 的优化
    • 1、优化了编码的逻辑组织
    • 2、优化了代码的逻辑复用


前言

在这里插入图片描述

一、源码优化

1、vue3.x 采用 monorep 的理念来管理源码

截止2023年年底,最新的 vue2.x 源码 和 vue3.x 源码 的核心部分,项目结构的“管理方式”对比:
在这里插入图片描述在这里插入图片描述
(左边是 vue2.x 源码目录)(右边是 vue3.x 源码目录)

可见:

  • vue2.x 的源码托管在 src 目录下,依据功能拆分成了不同的模块;vue3.x 的源码主要是使用 monorep 的理念来开发和维护的——根据功能将不同的模块拆分到 packages 目录下面。这种变化,具有以下优点:
    • 每个 package 有各自的 API、类型定义 和 测试,这使得模块拆分更细化、职责更明确、依赖关系更明确,更易于开发者使用,从而提升了自身代码的可维护性。
    • 部分 package(比如:reactive 响应式库)可以独立于 vue.js 使用,减小了引用包的体积大小。

2、vue3.x 源码采用 TypeScript 开发

vue3.x 源码全面采用 TypeScript 开发,在编码期间 TS 会自动做类型检查,避免一些类型错误导致的问题。
vue2.x 源码一开始是用 javascript 开发的,类型检查是用 Flow.js 实现的。在 vue3.0 推出以后,用 TypeScript 重构过了。

二、性能优化

1、减少源码的体积

移除了一些冷门的 feature。比如:Filters(过滤器)、inline-template等(https://blog.csdn.net/m0_62018311/article/details/131011249)
引入 tree-shaking 的技术,减少打包的体积——依赖于ES2015(ES6)的import和export模块语法,通过编译阶段的静态分析,找到没有引入的模块并打上标记,在打包时将这些被标记的模块忽略掉。这样也就间接达到了减少项目引入的 Vue.js 包体积的目的。

2、数据劫持优化

vue 的一大特色是它的数据是响应式的——DOM是数据的映射,数据变化后可以自动更新DOM。
实现“数据响应式”,必须劫持数据的访问和更新。
那么vue怎么知道更新哪一片DOM呢?
在渲染DOM的时候访问了数据,我们可以对它进行访问劫持,这样就在内部建立的依赖关系,也就知道对应的DOM是什么了。实际的实现要比这更复杂,内部依赖了一个watcher结构来管理这些依赖:
在这里插入图片描述
vue2.x 通过 Object.defineProperty 这个API劫持数据的getter和setter:

Object.defineProperty(data, 'a', {get() {},set(){}
})

但这个API有些缺陷:

  • 它必须先知道要拦截的key是什么,所以它并不能检测对象属性的添加和删除。vue2.x 为了解决这个问题增加了 $set 和 $delete 的实例方法,这无疑给使用者增加了额外的心智负担。
  • 如果我们定义的数据过于复杂,就会有相当大的性能负担。这是因为:vue 无法判断你在运行时到底要访问哪个属性,所以对于一个嵌套层级较深的对象,如果要劫持到它内部深层次的对象的变化,就需要递归便利这个对象,执行 Object.defineProperty 把每一层对象都变成响应式的对象的。

为了解决上述两个问题,vue3.x 采用了 Proxy API来做数据劫持:

const observed = new Proxy(data, {get() {},set(){}
})

由于它劫持的是整个对象,所以自然对整个对象的删除和增加都能检测到。
但是,Proxy API并不能监听到内部深层次的对象的变化。因此,vue3.x 采用了在 getter 中去递归响应式。这样的好处是,真正访问到的内部对象才会变成响应式,而不是无脑递归。这无疑大大提升了性能。

3、编译优化

下图是 vue2.x 从创建 vue 实例开始到渲染成 DOM 的过程:
在这里插入图片描述
上面说过的响应式就是发生在图中的 init 阶段。
另外,“template compiled to render function” 的流程可以借助 view-loader 在 webpack 编译阶段离线完成,并非一定要在运行时完成。所以想要优化整个vue.js的运行时,除了数据部分的优化,还可以在耗时较多的patch阶段想办法。于是,vue3.x 在编译阶段优化了编译的结果,来实现了运行时 patch 阶段的优化。

(1)、编译粒度的优化

vue2.x 的数据更新并触发重新渲染的粒度是组件级的:
在这里插入图片描述
虽然,vue2.x 能保证触发更新的组件最小化,但是单个组件内部依然需要遍历该组件的整个 v-node 树,比如我们要更新以下组件:

<template>
<div id="content"><p>1</p><p>2</p><p>{{number}}</p><p>4</p><p>5</p>
</div>
</template>

一个div中有5个p标签,只有第3个p标签是动态数据number,整个diff过程如图所示:
在这里插入图片描述
可以看到,因为这段代码只有一个动态节点, 所以这里有很多的diff和遍历都是不需要的。这就导致 v-node 的性能和模板大小正相关,跟动态节点数量无关。当一些组件整个模板只有少量动态节点时,这些便利都是性能的浪费,理想状态只需要diff这个绑定number的p标签即可。vue.3.x 做到了。

vue.3.x 通过编译阶段对静态模板的分析,编译生成了 block tree:

  • block tree 是一个模板基于动态节点指令切割的嵌套区块,每个区块内部节点结构是固定的。
  • block tree 的每个区块只需要以一个Array来追踪自身包含的动态节点。

借助 block tree,vue.js 将 v-node 更新性能由与模板整体大小正相关提升为与动态内容的数量相关。这是一个非常大的性能突破。

除此之外,vue3.x 在编译阶段还做了:slot编译优化、事件侦听函数的缓存优化、运行时重写diff算法,这些之后会说。

三、语法 API 的优化

vue3.x 推出了 Composition API 。

Composition API 相较于 Options API 的优势:

  • Composition API 优化了编码的逻辑组织——将某个逻辑关注点的相关代码全部放在一个函数里。
  • Composition API 优化了代码的逻辑复用——使用 hooks 取代了 mixin。

1、优化了编码的逻辑组织

相较于 Options API,Composition API 优化了编码的逻辑组织。

Options API 的好处是写法非常符合人的逻辑思维,对新手比较友好——Options API 的设计是按照 method、computed、data、props 这些不同的选项分类的。当组件小的时候这种分类方式一目了然,但是在大型组件中,一个组件可能有多个逻辑关注点,当使用 Options API 的时候,每个关注点都有自己的 options,如果需要修改一个逻辑的关注点,就需要在单个文件中不断的上下切换寻找。

Composition API 解决了这个问题,就是将某个逻辑关注点相关的代码全部放到一个函数里,这样当需要修改一个功能时就不需要在文件中跳来跳去了。
在这里插入图片描述

2、优化了代码的逻辑复用

在 vue2.x 的 Options API 中,可以使用 mixin 来做代码的逻辑复用。使用单个 mixin 的问题不大,但是当我们的组件混入大量不同的 mixin 的时候,会存在两个非常明显的问题:

  • 命名冲突:每个 mixin 都可以定义自己的 props、data,他们之间是无感的,所以很容易定义相同的变量名,导致命名冲突。
  • 数据来源不清晰:对组件而言,如果模板中使用不在当前组件中定义的变量,那么就不会太容易知道这些变量在哪里定义的,这就是数据来源不清晰。

mixin 的以上问题在 Composition API 中均得到了解决——定义 hook 函数,在组件中使用 hook 函数。

Composition API 除了在逻辑复用方面有优势,还有更好的类型支持。因为他们都是一些函数,在调用函数时,自然所有的类型都被推导出来了。不像 Options API 所有的东西都使用 this。

另外,Composition API 对 tree-shaking 友好,代码也更容易压缩。

虽然 Composition API 有诸多优势,它也有一定的缺陷,之后再说。

关于 Composition API 的具体实现和设计原理,也在之后说。




【参考资源】
vue3.x 的源码 github 地址
vue3 源码解析教程
全网最详细 Vue3 源码解析

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

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

相关文章

webpack学习-6.缓存

webpack学习-6.缓存 1.前言2.输出文件的文件名3. 提取引导模板4.模块标识符5.总结 1.前言 webpack 会在打包后生成可部署的 /dist 目录&#xff0c;并将打包后的内容放在此目录。一旦 /dist 目录中的内容部署到服务器上&#xff0c;客户端&#xff08;通常是浏览器&#xff09…

Linux操作系统:自由、稳定、强大的开源之光

导言 Linux操作系统作为一个开源的、多用户、多任务、支持多线程和多CPU的UNIX类操作系统&#xff0c;不仅在服务器领域占有显著份额&#xff0c;也逐渐在桌面和嵌入式系统中崭露头角。Linux操作系统的多样性体现在各种不同的发行版上&#xff0c;而Ubuntu、CentOS和Red Hat可以…

C# WPF上位机开发(进度条操作)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 软件上面如果一个操作比较缓慢&#xff0c;或者说需要很长的时间&#xff0c;那么这个时候最好添加一个进度条&#xff0c;提示一下当前任务的进展…

SQL进阶理论篇(十一):什么是MVCC?

文章目录 简介什么是MVCC快照读与当前读悲观锁的问题示例参考文献 简介 在MySQL中&#xff0c;默认的隔离级别是可重复读&#xff0c;可以解决脏读和不可重复读的问题&#xff0c;但不能解决幻读问题。如果想要解决幻读问题&#xff0c;就需要采用串行化的方式&#xff0c;通过…

js中for-in和for-of的区别

文章目录 一、介绍1.1、for-in1.2、for-of 二、区别2.1、迭代对象的内容不同2.2、迭代对象的类型不同2.3、迭代对象的顺序不同2.4、迭代对象的原理不同 三、联系四、如何选择合适的循环方法五、总结六、最后 一、介绍 在JavaScript中&#xff0c;for-in 和 for-of 是两种不同的…

详细教程 - 从零开发 Vue 鸿蒙harmonyOS应用 第六节(js版) ——模块化设计实现复杂页面

随着HarmonyOS生态的日渐完善,越来越多的厂商加入鸿蒙系统应用开发的行列。然而从其他系统转到鸿蒙开发,很多开发者还是需要一个适应的过程,特别是面对比较复杂的页面,应该如何合理进行模块化拆分是一个难点。 本文将通过一个实例,来分析如果采用模块化的方式实现一个包含丰富内…

【个人版】SpringBoot下Spring-Security自定义落地篇【四】

SpringBoot Spring-Security 背景&#xff1a; 上篇文章在源码读取的基础上&#xff0c;根据自身代码习惯及需求&#xff0c;总结了一个自定义简单落地版本。后来在看到松哥写的博文&#xff08;不太爱看官网&#xff09;&#xff0c;发现还有新的变种模式&#xff0c;虽然整…

mysql使用全文索引+ngram全文解析器进行全文检索

表结构&#xff1a;表名 gamedb 主键 id 问题类型 type 问题 issue 答案 answer 需求 现在有个游戏资料库储存在mysql中&#xff0c;客户端进行搜索&#xff0c;需要对三个字段进行匹配&#xff0c;得到三个字段的相关性&#xff0c;选出三个字段中相关性最大的值进…

【MYSQL】-库的操作

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

前端框架如何帮助开发者构建应用程序?

目录 前言 1.项目简介 2. 平台特性 2.1 构架特性 2.2 功能特性 3. 整体架构 4. 技术栈 平台的开放性&#xff1a; 平台高拓展性&#xff1a; 5. 基础功能及搭建 5.1 代码生成器 5.2 工作流程 5.3 门户设计 5.4 大屏设计 5.5 报表设计 5.6 第三方登录 5.7 多租…

vscode 同步插件

vscode 扩展商店链接 https://marketplace.visualstudio.com/vscode settings sync 插件

apache shiro 反序列化漏洞解决方案

apache shiro 反序列化漏洞解决方案 反序列化漏洞解决方案产生原因解决方案1&#xff1a;1.升级shiro至最新版本1.7.1解决方案2&#xff1a;修改rememberMe默认密钥&#xff0c;生成随机密钥。 反序列化漏洞解决方案 反序列化漏洞介绍 序列化&#xff1a;把对象转换为字符串或…

opencv、pillow和matplotlib的区别

参考文章&#xff1a;Python学习小技巧——opencv、pillow和matplotlib的区别_pillow和opencv区别-CSDN博客 1 概念的比较&#xff1a; opencv &#xff08;1&#xff09;默认不支持中文文件名 &#xff08;2&#xff09;数据为numpy&#xff0c;维度&#xff1a;高&#xff…

图片速览 PoseGPT:基于量化的 3D 人体运动生成和预测(VQVAE)

papercodehttps://arxiv.org/pdf/2210.10542.pdfhttps://europe.naverlabs.com/research/computer-vision/posegpt/ 方法 将动作压缩到离散空间。使用GPT类的模型预测未来动作的离散索引。使用解码器解码动作得到输出。 效果 提出的方法在HumanAct12&#xff08;一个标准但小规…

AWS-WAF-CDN基于速率rate的永久黑名单方案(基于lambda实现)

参考方案&#xff08;有坑&#xff09;&#xff0c; 所以产生了这篇博客&#xff1a; 点击跳转 1. 部署waf &#xff08;有则跳过&#xff09; 必须存在一个rate速率规则&#xff0c;后面的方案堆栈要用 新建rate速率规则 关联cdn资源 2.部署堆栈 (美国东部 (弗吉尼亚北部 …

短视频账号剪辑矩阵系统源码技术3年自研开发框架

短视频账号剪辑矩阵系统源码技术3年自研开发框架&#xff0c;这个市场截至到现在基本上违规开发的&#xff0c;没有正规接口开发的&#xff0c;基本上都已经筛选完了&#xff0c;目前各位技术者公司想要考察的话&#xff0c;只需要甄别3方面即可 1.剪辑是不是自己核心研发的&a…

正则表达式:简化模式匹配的利器

正则表达式&#xff1a;简化模式匹配的利器 一、正则表达式简介1.1 正则表达式介绍1.2 正则表达式使用场景 二、正则表达式语法2.1 正则表达式元字符和特性2.2 正则表达式常用匹配 三、正则表达式实战3.1 常见的正则表达式用法3.2 正则表达式的过滤用法3.3 正则表达式的代码用法…

Hadoop Single Node Cluster的安装

Hadoop Single Node Cluster的安装 安装JDK查看java -version更新本地软件包安装JDK查看java安装位置 设置SSH无密码登录安装hadoop下载安装设置hadoop环境变量修改hadoop配置设置文件设置core-site.xml设置YARN-site.xml设置mapred-site.xml设置HDFS分布式文件系统创建并格式化…

华为配置OSPF与BFD联动示例

组网需求 如图1所示&#xff0c;SwitchA、SwitchB和SwitchC之间运行OSPF&#xff0c;SwitchA和SwitchB之间的交换机仅作透传功能。现在需要SwitchA和SwitchB能快速感应它们之间的链路状态&#xff0c;当链路SwitchA-SwitchB发生故障时&#xff0c;业务能快速切换到备份链路Swi…

HTML---CSS美化网页元素

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.div 标签&#xff1a; <div>是HTML中的一个常用标签&#xff0c;用于定义HTML文档中的一个区块&#xff08;或一个容器&#xff09;。它可以包含其他HTML元素&#xff0c;如文本、图像…