「Vue3面试系列」Vue3.0性能提升主要是通过哪几方面体现的?

文章目录
- 一、编译阶段
- diff算法优化
- 静态提升
- 事件监听缓存
- SSR优化
- 二、源码体积
- 三、响应式系统
- 参考文献
一、编译阶段
回顾Vue2,我们知道每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把用到的数据property记录为依赖,当依赖发生改变,触发setter,则会通知watcher,从而使关联的组件重新渲染

试想一下,一个组件结构如下图
<template><div id="content"><p class="text">静态文本</p><p class="text">静态文本</p><p class="text">{{ message }}</p><p class="text">静态文本</p>...<p class="text">静态文本</p></div>
</template>
可以看到,组件内部只有一个动态节点,剩余一堆都是静态节点,所以这里很多 diff 和遍历其实都是不需要的,造成性能浪费
因此,Vue3在编译阶段,做了进一步优化。主要有如下:
- diff算法优化
- 静态提升
- 事件监听缓存
- SSR优化
diff算法优化
vue3在diff算法中相比vue2增加了静态标记
关于这个静态标记,其作用是为了会发生变化的地方添加一个flag标记,下次发生变化的时候直接找该地方进行比较
下图这里,已经标记静态节点的p标签在diff过程中则不会比较,把性能进一步提高

关于静态类型枚举如下
export const enum PatchFlags {TEXT = 1,// 动态的文本节点CLASS = 1 << 1, // 2 动态的 classSTYLE = 1 << 2, // 4 动态的 stylePROPS = 1 << 3, // 8 动态属性,不包括类名和样式FULL_PROPS = 1 << 4, // 16 动态 key,当 key 变化时需要完整的 diff 算法做比较HYDRATE_EVENTS = 1 << 5, // 32 表示带有事件监听器的节点STABLE_FRAGMENT = 1 << 6, // 64 一个不会改变子节点顺序的 FragmentKEYED_FRAGMENT = 1 << 7, // 128 带有 key 属性的 FragmentUNKEYED_FRAGMENT = 1 << 8, // 256 子节点没有 key 的 FragmentNEED_PATCH = 1 << 9, // 512DYNAMIC_SLOTS = 1 << 10, // 动态 soltHOISTED = -1, // 特殊标志是负整数表示永远不会用作 diffBAIL = -2 // 一个特殊的标志,指代差异算法
}
静态提升
Vue3中对不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用
这样就免去了重复的创建节点,大型应用会受益于这个改动,免去了重复的创建操作,优化了运行时候的内存占用
<span>你好</span><div>{{ message }}</div>
没有做静态提升之前
export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createBlock(_Fragment, null, [_createVNode("span", null, "你好"),_createVNode("div", null, _toDisplayString(_ctx.message), 1 /* TEXT */)], 64 /* STABLE_FRAGMENT */))
}
做了静态提升之后
const _hoisted_1 = /*#__PURE__*/_createVNode("span", null, "你好", -1 /* HOISTED */)export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createBlock(_Fragment, null, [_hoisted_1,_createVNode("div", null, _toDisplayString(_ctx.message), 1 /* TEXT */)], 64 /* STABLE_FRAGMENT */))
}// Check the console for the AST
静态内容_hoisted_1被放置在render 函数外,每次渲染的时候只要取 _hoisted_1 即可
同时 _hoisted_1 被打上了 PatchFlag ,静态标记值为 -1 ,特殊标志是负整数表示永远不会用于 Diff
事件监听缓存
默认情况下绑定事件行为会被视为动态绑定,所以每次都会去追踪它的变化
<div><button @click = 'onClick'>点我</button>
</div>
没开启事件监听器缓存
export const render = /*#__PURE__*/_withId(function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createBlock("div", null, [_createVNode("button", { onClick: _ctx.onClick }, "点我", 8 /* PROPS */, ["onClick"])// PROPS=1<<3,// 8 //动态属性,但不包含类名和样式]))
})
开启事件侦听器缓存后
export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createBlock("div", null, [_createVNode("button", {onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick(...args)))}, "点我")]))
}
上述发现开启了缓存后,没有了静态标记。也就是说下次diff算法的时候直接使用
SSR优化
当静态内容大到一定量级时候,会用createStaticVNode方法在客户端去生成一个static node,这些静态node,会被直接innerHtml,就不需要创建对象,然后根据对象渲染
div><div><span>你好</span></div>... // 很多个静态属性<div><span>{{ message }}</span></div>
</div>
编译后
import { mergeProps as _mergeProps } from "vue"
import { ssrRenderAttrs as _ssrRenderAttrs, ssrInterpolate as _ssrInterpolate } from "@vue/server-renderer"export function ssrRender(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) {const _cssVars = { style: { color: _ctx.color }}_push(`<div${_ssrRenderAttrs(_mergeProps(_attrs, _cssVars))}><div><span>你好</span>...<div><span>你好</span><div><span>${_ssrInterpolate(_ctx.message)}</span></div></div>`)
}
二、源码体积
相比Vue2,Vue3整体体积变小了,除了移出一些不常用的API,再重要的是Tree shanking
任何一个函数,如ref、reavtived、computed等,仅仅在用到的时候才打包,没用到的模块都被摇掉,打包的整体体积变小
import { computed, defineComponent, ref } from 'vue';
export default defineComponent({setup(props, context) {const age = ref(18)let state = reactive({name: 'test'})const readOnlyAge = computed(() => age.value++) // 19return {age,state,readOnlyAge}}
});
三、响应式系统
vue2中采用 defineProperty来劫持整个对象,然后进行深度遍历所有属性,给每个属性添加getter和setter,实现响应式
vue3采用proxy重写了响应式系统,因为proxy可以对整个对象进行监听,所以不需要深度遍历
- 可以监听动态属性的添加
- 可以监听到数组的索引和数组
length属性 - 可以监听删除属性
关于这两个 API 具体的不同,我们下篇文章会进行一个更加详细的介绍
参考文献
- https://juejin.cn/post/6903171037211557895
相关文章:
「Vue3面试系列」Vue3.0性能提升主要是通过哪几方面体现的?
文章目录 一、编译阶段diff算法优化静态提升事件监听缓存SSR优化 二、源码体积三、响应式系统参考文献 一、编译阶段 回顾Vue2,我们知道每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把用到的数据property记录为依赖,当依赖发…...
网络结构模式
一、C/S结构 服务器 - 客户机,即 Client - Server ( C/S )结构。 C/S 结构通常采取两层结构。服务器负责数据的 管理,客户机负责完成与用户的交互任务。客户机是因特网上访问别人信息的机器,服务器则是提 供信息供人…...
IIC及OLED实验
I2C (Inter-Integrated Circuit): I2C 是一种用于在芯片之间进行短距离数字通信的串行通信协议。它允许多个设备通过两根导线(一根数据线 SDA 和一根时钟线 SCL)进行通信。I2C 常常用于嵌入式系统中连接传感器、存储器、显示屏和其他外设。 数据线和时钟…...
day6 力扣公共前缀--go实现---对字符串的一些思考
今日份知识: curl -x 指定方法名 请求的url -d 请求体body里面的内容 //curl命令 curl -x Get 127.0.0.1:8080/add/user -d jinlicurl如果不指定方法,默认使用get方法,在go里面,get方法到底可以不可以把内容数据写在body里面传…...
27.Java程序设计-基于Springboot的在线考试系统小程序设计与实现
1. 引言 随着数字化教育的发展,在线考试系统成为教育领域的一项重要工具。本论文旨在介绍一个基于Spring Boot框架的在线考试系统小程序的设计与实现。在线考试系统的开发旨在提高考试的效率,简化管理流程,并提供更好的用户体验。 2. 系统设…...
Redis可视化工具Redis Desktop Manager mac功能特色
Redis Desktop Manager mac是一款非常实用的Redis可视化工具。RDM支持SSL / TLS加密,SSH隧道,基于SSH隧道的TLS,为您提供了一个易于使用的GUI,可以访问您的Redis数据库并执行一些基本操作:将键视为树,CRUD键…...
【C++】揭开运算符重载的神秘面纱
目录 一、引言 优点 二、介绍 1.定义 2.语法 三、示例 1.加法运算符重载 2.一元运算符重载 3.友元函数 4.流插入和流提取 5.自增自减运算符 总结 一、引言 何为运算符重载?运算符重载,是C中的一项强大特性,赋予了程序员在自定义类…...
竞赛保研 基于LSTM的天气预测 - 时间序列预测
0 前言 🔥 优质竞赛项目系列,今天要分享的是 机器学习大数据分析项目 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/po…...
前端常用的开发工具
前端常用的开发工具🔖 文章目录 前端常用的开发工具🔖1. Snipaste--截图工具2. ScreenToGif--gif图片录制3. Typora--Markdown编辑器4. notepad--文本代码编辑器5. uTools--多功能工具6. EV录屏--录屏软件7. Xmind--思维导图8. Apifox -- 接口调试9. Tor…...
鸿蒙开发语言介绍--ArkTS
1.编程语言介绍 ArkTS是HarmonyOS主力应用开发语言。它在TypeScript (简称TS)的基础上,匹配ArkUI框架,扩展了声明式UI、状态管理等相应的能力,让开发者以更简洁、更自然的方式开发跨端应用。 2.TypeScript简介 自行补充TypeScript知识吧。h…...
关于“Python”的核心知识点整理大全36
目录 13.4.4 向下移动外星人群并改变移动方向 game_functions.py alien_invasion.py 13.5 射杀外星人 13.5.1 检测子弹与外星人的碰撞 game_functions.py alien_invasion.py 13.5.2 为测试创建大子弹 13.5.3 生成新的外星人群 game_functions.py alien_invasion.py …...
安装nodejs,配置环境变量并将npm设置淘宝镜像源
安装nodejs并将npm设置淘宝镜像源 1. 下载nodejs 个人不喜欢安装包,所以是下载zip包的方式。这里我下载的node 14解压包版本 下载地址如下:https://nodejs.org/dist/v14.15.1/node-v14.15.1-win-x64.zip 想要其他版本的小伙伴去https://nodejs.org/di…...
12.18构建哈夫曼树(优先队列),图的存储方式,一些细节(auto,pair用法,结构体指针)
为结构体自身时,用.调用成员变量;为结构体指针时,用->调用成员变量 所以存在结构体数组时,调用数组元素里的成员变量,就是要用. 结构体自身只有在new时才会创建出来,而其指针可以随意创建 在用new时&…...
《Python》面试常问:深拷贝、浅拷贝、赋值之间的关系(附可变与不可变)【用图文讲清楚!】
背景 想必大家面试或者平时学习经常遇到问python的深拷贝、浅拷贝和赋值之间的区别了吧?看网上的文章很多写的比较抽象,小白接收的难度有点大,于是乎也想自己整个文章出来供参考 可变与不可变 讲深拷贝和浅拷贝之前想讲讲什么是可变数据类型…...
使用PE信息查看工具和Dependency Walker工具排查因为库版本不对导致程序启动报错问题
目录 1、问题说明 2、问题分析思路 3、问题分析过程 3.1、使用Dependency Walker打开软件主程序,查看库与库的依赖关系,查看出问题的库 3.2、使用PE工具查看dll库的时间戳 3.3、解决办法 4、最后 VC常用功能开发汇总(专栏文章列表&…...
Python编程题目答疑「Python一对一辅导考试真题解析」
你好,我是悦创。 待会更新~ 更新计划 答案 题目 记得点赞收藏! 题目 之后更新 Solution Question 1 # 读取输入 a float(input("请输入实数 a: ")) b float(input("请输入实数 b: ")) c float(input("请输…...
Python---搭建Python自带静态Web服务器
1. 静态Web服务器是什么? 可以为发出请求的浏览器提供静态文档的程序。 平时我们浏览百度新闻数据的时候,每天的新闻数据都会发生变化,那访问的这个页面就是动态的,而我们开发的是静态的,页面的数据不会发生变化。 …...
在服务器上部署SpringBoot项目jar包
以下是在服务器上部署Spring Boot项目jar包的步骤: 打包项目: 使用IDEA或者命令行工具(如Maven或Gradle)将Spring Boot项目打包为一个可执行的jar文件。如果使用Maven,可以在项目的根目录下运行以下命令来打包项目&…...
[python]python实现对jenkins 的任务触发
目录 关键词平台说明背景一、安装 python-jenkins 库二、code三、运行 Python 脚本四、注意事项 关键词 python、excel、DBC、jenkins 平台说明 项目Valuepython版本3.6 背景 用python实现对jenkins 的任务触发。 一、安装 python-jenkins 库 pip install python-jenkin…...
Python生成圣诞节贺卡-代码案例剖析【第18篇—python圣诞节系列】
文章目录 ❄️Python制作圣诞节贺卡🐬展示效果🌸代码🌴代码剖析 ❄️Python制作圣诞树贺卡🐬展示效果🌸代码🌴代码剖析🌸总结 🎅圣诞节快乐! ❄️Python制作圣诞节贺卡 …...
DataX 实战:从零部署到多场景数据同步
1. DataX入门:为什么选择它作为数据同步工具 第一次接触DataX是在三年前的一个紧急项目里,当时需要把生产环境的MySQL数据实时同步到分析库。试过几种方案后,最终被DataX的稳定性和灵活性打动。作为阿里开源的数据同步工具,它最大…...
极域电子教室突破技术:从系统控制到自主操作的攻防对抗
极域电子教室突破技术:从系统控制到自主操作的攻防对抗 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 一、核心痛点:极域电子教室的控制枷锁 在信息化教…...
深入Linux tcpm框架:从FUSB302芯片看PD协议兼容性那些‘坑’
深入Linux tcpm框架:从FUSB302芯片看PD协议兼容性那些‘坑’ Type-C接口凭借其强大的供电能力和灵活的数据传输特性,已成为现代电子设备的标配。然而,在Linux系统中实现完美的PD协议兼容性,却是一场充满技术陷阱的冒险。本文将带您…...
从演唱会踩踏到交通拥堵:我们如何用无人机双光人群计数,为城市装上‘智慧之眼’?
无人机双光人群计数:城市安全管理的智能升级之路 当夜幕降临,体育场外数万观众正陆续离场,安保指挥中心的大屏上闪烁着红黄相间的热力图——这不是科幻电影的场景,而是某省会城市在明星演唱会后的真实一幕。通过部署在关键节点的1…...
如何快速创建专业图表:Mermaid数据可视化的完整指南
如何快速创建专业图表:Mermaid数据可视化的完整指南 【免费下载链接】mermaid mermaid-js/mermaid: 是一个用于生成图表和流程图的 Markdown 渲染器,支持多种图表类型和丰富的样式。适合对 Markdown、图表和流程图以及想要使用 Markdown 绘制图表和流程图…...
猫抓资源嗅探扩展:5大核心功能彻底解析网络媒体捕获技术
猫抓资源嗅探扩展:5大核心功能彻底解析网络媒体捕获技术 【免费下载链接】cat-catch 猫抓 chrome资源嗅探扩展 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 猫抓(Cat-Catch)是一款开源免费的浏览器资源嗅探扩展&…...
OpenClaw+nanobot自动化测试:24小时监控网站可用性
OpenClawnanobot自动化测试:24小时监控网站可用性 1. 为什么需要自动化网站监控 作为个人站长,我经常遇到这样的困扰:半夜网站突然宕机,直到第二天收到用户反馈才发现问题。传统监控方案要么价格昂贵,要么配置复杂&a…...
从仿真到AI数据集:一条龙搞定COMSOL+MATLAB+Python数据处理流水线
从仿真到AI数据集:COMSOLMATLABPython全流程自动化实践 在物理仿真与机器学习融合的研究中,最耗时的往往不是算法设计,而是高质量数据集的构建。想象一下这样的场景:你需要在数百组参数组合下运行电磁场仿真,每次仿真生…...
玩转LS-DYNA爆破模拟:倾斜长短孔布孔实战
ANSYS/ls-dyna隧道、巷道爆破倾斜长短孔布孔方式下爆破损伤数值模拟 1.讲述小间隔长短型炮孔爆破模型的建模及网格划分全过程,包含网格尺寸设计。 2.装药结构修改,可实现长短炮孔中间隔装药、设置空孔,延期起爆、起爆位置等设置,讲…...
深入解析ACS SPiiPlus运动控制器的托管接口设计与实现
1. ACS SPiiPlus运动控制器托管接口概述 在工业自动化领域,运动控制器的性能直接影响着设备的精度和效率。ACS SPiiPlus系列作为业内知名的高性能运动控制器,其托管接口设计一直是工程师们关注的焦点。这套接口本质上是一套软件中间层,它架起…...
