vue 历程记

news2024/11/26 23:37:30

目录

  • 前言
  • 一、源码优化
    • 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.coloradmin.cn/o/1320750.html

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

相关文章

install cuda cudnn tersorRT

# 安装 $ ubuntu-drivers devices$ sudo apt-get install nvidia-driver-470-server # 推荐是server&#xff0c;都可以。#delelt sudo apt --purge remove nvidia-* CUDA Toolkit Archive | NVIDIA Developerhttps://developer.nvidia.com/cuda-toolkit-archive CUDA Toolk…

MongoDB的数据库引用

本文主要介绍MongoDB的数据库引用。 目录 MongoDB的数据库引用 MongoDB的数据库引用 MongoDB是一种面向文档的NoSQL数据库&#xff0c;它使用BSON&#xff08;Binary JSON&#xff09;格式存储和查询数据。在MongoDB中&#xff0c;数据库引用是一种特殊的数据类型&#xff0c;…

最新AI创作系统ChatGPT系统源码+DALL-E3文生图+支持AI绘画+GPT语音对话功能

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

Leetcode—859.亲密字符串【简单】

2023每日刷题&#xff08;六十三&#xff09; Leetcode—859.亲密字符串 &#x1f4a9;山实现代码 class Solution { public:bool buddyStrings(string s, string goal) {int len1 s.size(), len2 goal.size();int cnt 0;int flag 0;int flag2 0;int odd -1;int a[26] …

python 实现 AIGC 大模型中的概率论:生日问题的公式推导

在前两节中&#xff0c;我们推导了生日问题的求解算法&#xff0c;但在数学上的最终目标就是希望能针对问题推导出一个简洁漂亮的公式&#xff0c;就像爱因斯坦著名的质能方程 E MC^2 那样&#xff0c;毕竟数学是以符号逻辑来看待世界本质的语言&#xff0c;所以絮絮叨叨不是数…

AXure的情景交互

目录 导语&#xff1a; 1.erp多样性登录界面 2.主页跳转 3.省级联动​编辑 4. 下拉加载 导语&#xff1a; Axure是一种流行的原型设计工具&#xff0c;可以用来创建网站和应用程序的交互原型。通过Axure&#xff0c;设计师可以创建情景交互&#xff0c;以展示用户与系统的交…

Elasitcsearch--解决CPU使用率升高

原文网址&#xff1a;Elasitcsearch--解决CPU使用率升高_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何解决ES导致的CPU使用率升高的问题。 问题描述 线上环境 Elasticsearch CPU 使用率飙升常见问题如下&#xff1a; Elasticsearch 使用线程池来管理并发操作的 CPU 资源。…

JVM-11-运行时栈帧结构

“栈帧”&#xff08;Stack Frame&#xff09;则是用于支持虚拟机进行方法调用和方法执行背后的数据结构&#xff0c;它也是虚拟机运行时数据区中的虚拟机栈&#xff08;Virtual MachineStack&#xff09;的栈元素。 栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回…

【web安全】支付篡改

前言 菜某的总结&#xff0c;如有错误和补充欢迎评论指正。 内容仅供学习使用&#xff0c;切勿用于非法用途。 支付篡改的存在位置与影响 首先他的危害不言而喻&#xff0c;几乎任何一个拿出来都能给企业带来巨大的损失。 他出现的地方也是十分的广泛&#xff0c;从某种意…

opencv、pillow和matplotlib的区别

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

【uniapp小程序-上拉加载】

在需要上拉加载的页面的page.json上添加红框框里面的 onReachBottom() {if(this.commentCurrent<this.commentTotal){this.commentCurrent 1; this.commentList();this.status loading;}else{this.status ;} }, methods:{commentList(){let params {courseid:this.cour…

超级计算机与天气预报:精准预测的科技革命

超级计算机与天气预报&#xff1a;精准预测的科技革命 一、引言 随着科技的飞速发展&#xff0c;超级计算机已经成为现代社会不可或缺的一部分。它们在科研、工业、军事等领域发挥着重要作用&#xff0c;其中天气预报是一个颇具代表性的应用领域。本文将探讨超级计算机在天气…

_55跳跃游戏 _45跳跃游戏II

_55跳跃游戏 && _45跳跃游戏II 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;_55跳跃游戏_45跳跃游戏II 参考代码&#xff1a;_55跳跃游戏_45跳跃游戏II_从覆盖范围角度考虑_45跳跃游戏II 错误经验吸取 原题链接&#xff1a; _55跳跃游戏 &&…

文件包含的提升刷题

上一篇文章&#xff1a;一篇文章带你入门文件包含-CSDN博客 已经开始入门了文件包含&#xff0c;那现在开始拔高提升刷题&#xff01; 1. 拿到题目后啥也没有&#xff0c;所以也不知道要读取啥文件&#xff0c;那就查看源代码。 直接看if的条件就可以知道一定要设置cookie&a…

leecode题解Golang版本-3-无重复字符最长子串

题目 无重复字符最长子串 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 题解 func lengthOfLongestSubstring(s string) int {m : make(map[uint8]int)res : 0for l, r : 0, 0; r < len(s); r {m[s[r]]if v, ok : m[s[r]]; !ok || v 1…

「Verilog学习笔记」流水线乘法器

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1nsmodule multi_pipe#(parameter size 4 )(input clk , input rst_n ,input [size-1:0] mul_a ,input [size-1:0] mul_b ,output …

PyTorch官网demo解读——第一个神经网络(2)

上一篇&#xff1a;PyTorch官网demo解读——第一个神经网络&#xff08;1&#xff09; 继上一篇文章我们展示了第一个神经网络的完整代码&#xff0c;今天我们来聊聊这个神经网络的模型设计。 这个demo实际上只使用了一个简单的线性模型&#xff1a;y wx b&#xff1b; 手写…

测试大佬详解:黑盒测试的底层逻辑

什么是黑盒测试&#xff1f; 它是把程序看作一个黑盒子&#xff0c;在不考虑程序内部结构的情况下&#xff0c;检查程序功能是否按照PRD的规定正常使用&#xff0c;程序是否能适当地接收输入数据&#xff0c;产生正确的输出。 这其实就是黑盒测试的定义&#xff0c;也是黑盒测…

Linux---Ubuntu软件安装

1. 软件安装的介绍 Ubuntu软件安装有两种方式: 离线安装(deb文件格式安装&#xff09;在线安装(apt-get方式安装) 2. deb文件格式安装 是 Ubuntu 的安装包格式&#xff0c;可以使用 dpkg 命令进行软件的安装和卸载。 命令说明dpkg安装和卸载deb安装包 dpkg命令选项: 选项…

微服务——服务异步通讯(MQ高级)

MQ的一些常见问题 消息可靠性 生产者消息确认 返回ack&#xff0c;怎么感觉这么像某个tcp的3次握手。 使用资料提供的案例工程. 在图形化界面创建一个simple.queue的队列&#xff0c;虚拟机要和配置文件里面的一样。 SpringAMQP实现生产者确认 AMQP里面支持多种生产者确认的类…