浅谈 Vue3 静态提升和预字符串化

前言

很多朋友在看到 Vue3静态提升 的时候很不理解,不明白这句话到底是什么意思,今天我们就通过这篇日记来搞明白。如果有什么地方描述不正确,请多多指正

静态类型(前置信息)

判断节点是否为静态类型,是根据如下标识进行判断的,可以对照这个进行查看。

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基础示例

首先我们来看下面的这段代码,对于看过Vue的童鞋来讲是不陌生的吧,即使没有看过,看到如下的代码是不是觉得也很好理解。

<script setup>import { ref } from 'vue';const message = ref('努力搬砖,做大做强');
</script><template><!-- 这是静态节点 --><span>你好啊,帕努</span><!-- 这是动态节点 --><span>{{message}}</span>
</template>

将上面的代码转换成 虚拟DOM 后的图示。
在这里插入图片描述

对于上面的代码,vue3在创建 vNode 的时候,对不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用,这样就免去了重复的创建节点,大型应用会受益于这个改动,免去了重复的创建操作,优化了运行时候的内存占用

创建vNode

针对上面的示例代码,在进行创建 虚拟DOM 的时候,下面的代码分别是 vue2vue3 版本下各自的vNode,从这就能够看出一些差别。

Vue2 没有做静态提升

export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createBlock(_Fragment, null, [_createVNode("span", null, "你好啊,帕努"),  // 静态虚拟节点_createVNode("span", null, _toDisplayString(_ctx.message), 1 /* TEXT */)], 64 /* STABLE_FRAGMENT */))
}

Vue3 做静态提升


// 把静态节点提出到外部定义,用一个变量存储,便于后面直接取值使用
const SPAN_V_NODE = _createVNode("span", null, "你好啊,帕努");export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createBlock(_Fragment, null, [SPAN_V_NODE, // 静态虚拟节点_createVNode("span", null, _toDisplayString(_ctx.message), 1 /* TEXT */)], 64 /* STABLE_FRAGMENT */))
}

将静态虚拟节点提到外层,便于直接使用(只创建一次),下次就直接获取值放到对应的位置即可。避免了每次执行 render 函数的时候,都要去再次执行一次 _createVNode 函数。

如果是比较简单的项目,在性能上看不大出来,如果是比较大型的项目,那就能够很明显的看到界面卡顿(渲染慢),严重的甚至可能会造成 CPU 的使用率急速上升等明显问题。

通过上面的示例可能也看不出多大的效果(具体有多大的提升),下面将通过一段简单代码就能看出他们有多大的差距。

另辟蹊径解释

如果对于上面的代码如果还不能理解的话,下面再通过另外一个示例来讲一下。

在一个循环中,获取一个计算结果,然后通过这个结果再去计算打印,然后就能够看到两者差别。

没做静态提升

// 静态值,只会返回固定的18,
function getAgeFn() {console.log('被调用获取值')return  18;
}function render() {console.log('开始时间', new Date().getTime()) // 开始时间 1709628094030for (let i = 0; i < 10000; i++){console.log('获取到的值',i, i+getAgeFn() )}console.log('结束时间', new Date().getTime()) // 结束时间 1709628096175
}render()

总运行时长:1709628096175 - 1709628094030 = 2145

在这里插入图片描述

做了静态提升

function getAgeFn() {console.log('被调用获取值')return  18;
}function render() {console.log('开始时间', new Date().getTime()) // 1709627967983const age = getAgeFn();for (let i = 0; i < 10000; i++){console.log('获取到的值',i, i+age )}console.log('结束时间', new Date().getTime()) // 1709627968909
}render()

总运行时长: 1709627968909 - 1709627967983= 926;

在这里插入图片描述

通过上面两段代码运行时间差就能够明显的看出效果,没做静态提升运行时长是做了静态提升的 2.32倍(四舍五入)。

预字符串化

另外提到了静态提升,那么就不得不提一下 Vue3的 预字符串化,那这是什么呢?有什么作用呢?

我们在实际开发中,经常会有大量的静态节点,是不需要动态更改的。那这一部分能不能再进行优化一下呢?答案是可行的。

<div><ul><li>aaaaaa</li><li>aaaaaa</li><li>aaaaaa</li><li>aaaaaa</li><li>aaaaaa</li><li>aaaaaa</li></ul><div class="state"><span>{{state}}</span></div><div>

在vue2中,每个元素都会变成虚拟节点,这样就会出现一大堆的静态的虚拟节点。

在vue3中它会智能地发现这一点,如下图所示,我们可以很明显的感受到vue3性能的显著提升。

在这里插入图片描述

注意:必须是 大量连续 的静态内容才可以预字符串化哦,切记!目前是连续 20个静态节点 才会预字符串化

总结

静态提升

Vue 2 并没有像 Vue 3 中那样实现静态提升(Static Tree Hoisting)。在 Vue 2 中,模板编译后的渲染函数是动态创建的,每次渲染都需要重新生成一次。这导致了一些性能上的损失,特别是在大型应用中频繁重新渲染时。

Vue 3 引入了静态提升的概念,通过将模板编译为更具静态特性的代码,可以在编译阶段优化并提升静态节点,减少运行时的开销,从而提高性能。这是 Vue 3 在性能方面的一个重要改进之一。

预字符串化

在编译阶段会对模板进行分析和优化,将动态部分和静态部分分离,并将静态部分转换为字符串常量,以减少运行时的开销。

预字符串化可以帮助 Vue 3 在渲染过程中更快地生成虚拟 DOM,并减少不必要的计算,从而提高整体的渲染性能。这个优化技术有助于减少应用的启动时间和运行时的性能消耗,使得 Vue 3 在处理大型复杂应用时表现更加出色。

这些骚操作总结一句话就是【提高性能】

最后

如果这篇文章对你有所帮助,请咚咚大家的 发财黄金手指点赞,收藏

如果文章有描述错误或者有更好解决方案,也请大家多多 评论

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

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

相关文章

【BUUCTF Misc】通关 3.0

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

利用GPT开发应用001:GPT基础知识及LLM发展

文章目录 一、惊艳的GPT二、大语言模型LLMs三、自然语言处理NLP四、大语言模型LLM发展 一、惊艳的GPT 想象一下&#xff0c;您可以与计算机的交流速度与与朋友交流一样快。那会是什么样子&#xff1f;您可以创建哪些应用程序&#xff1f;这正是OpenAI正在助力构建的世界&#x…

Qt多弹窗实现包括QDialog、QWidget、QMainWindow

1.相关说明 独立Widget窗口、嵌入式Widget、嵌入式MainWindow窗口、独立MainWindow窗口等弹窗的实现 相关界面包含关系 2.相关界面 3.相关代码 mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include "tformdoc.h" #incl…

理解CPU指令执行:从理论到实践

理解CPU指令执行&#xff1a;从理论到实践 在探讨现代计算机的核心——中央处理单元&#xff08;CPU&#xff09;的工作原理时&#xff0c;我们经常遇到“时钟周期”和“指令执行”这两个概念。这些概念不仅对于理解CPU的性能至关重要&#xff0c;而且对于揭示计算机如何处理任…

挑战杯 基于深度学习的人脸表情识别

文章目录 0 前言1 技术介绍1.1 技术概括1.2 目前表情识别实现技术 2 实现效果3 深度学习表情识别实现过程3.1 网络架构3.2 数据3.3 实现流程3.4 部分实现代码 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的人脸表情识别 该项目较…

羊大师揭秘,羊奶有哪些好处和不足呢?

羊大师揭秘&#xff0c;羊奶有哪些好处和不足呢&#xff1f; 羊奶的好处主要包括&#xff1a; 营养丰富&#xff1a;羊奶中含有多种人体所需的营养成分&#xff0c;如蛋白质、脂肪、碳水化合物、矿物质和维生素等。尤其是蛋白质含量高&#xff0c;且易于人体吸收利用。 增强免…

Spring——Bean的作用域

bean的作用域 Bean Scope Scope说明singleton&#xff08;默认情况下&#xff09;为每个Spring IoC容器将单个Bean定义的Scope扩大到单个对象实例。prototype将单个Bean定义的Scope扩大到任何数量的对象实例。session将单个Bean定义的Scope扩大到一个HTTP Session 的生命周期…

Unity用Shader将一张图片变成描边图片素描风格。

环境&#xff1a; unity2021.3.x 效果&#xff1a; 实现核心思路(shader)&#xff1a; fixed4 frag (v2f i) : SV_Target {fixed4 col tex2D(_MainTex, i.uv);// 调整相似度bool isRedMatch abs(col.r - _TargetColor.r) < 0.15;bool isGreenMatch abs(col.g - _Target…

什么是系统工程(字幕)45

0 00:00:01,030 --> 00:00:03,910 那首先呢&#xff0c;我们就要 1 00:00:04,380 --> 00:00:05,974 加一个分流器了 2 00:00:05,974 --> 00:00:07,568 它是一个三通接头 3 00:00:07,568 --> 00:00:09,960 三通接头在这里嘛&#xff0c;拖上来 4 00:00:11,530 -…

代码随想录算法训练营第三十四天| 860.柠檬水找零 、406.根据身高重建队列 、452. 用最少数量的箭引爆气球

文章目录 1.柠檬水找零2.根据身高重建队列3.用最少数量的箭引爆气球 1.柠檬水找零 在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品&#xff0c;&#xff08;按账单 bills 支付的顺序&#xff09;一次购买一杯。 每位顾客只买一杯柠檬水&#xf…

【Photoshop2020版本】零基础笔记(一)

哈喽大家好~最近博客内容换方向了哈哈哈~换成“实用版”了。 今天给大家带来的是 PS 相关内容 其实我也是刚学PS&#xff0c;所以想着自己做笔记还不如发布出去&#xff0c;让大家都能看到&#xff0c;有兴趣的伙伴们&#xff0c;可以跟着我的笔记一块学习&#xff0c;这个专…

操作系统(笔记)(一)

1、操作系统的功能和目标 1.1功能 存储管理文件管理设备管理处理机管理进程管理 1.2目标 方便性&#xff1a;操作系统作为用户与计算机硬件系统之间的接口&#xff0c;提供了直观的命令和界面&#xff0c;使得用户能够更容易地操作计算机。有效性&#xff1a;操作系统旨在提…

将ppt里的视频导出来

将ppt的后缀从pptx改为zip 找到【media】里面有存放图片和音频以及视频&#xff0c;看文件名后缀可以找到&#xff0c;mp4的即为视频&#xff0c;直接复制粘贴到桌面即可。 关闭压缩软件把ppt后缀改回&#xff0c;不影响ppt正常使用。

【论文阅读】Mamba:选择状态空间模型的线性时间序列建模(二)

文章目录 3.4 一个简化的SSM结构3.5 选择机制的性质3.5.1 和门控机制的联系3.5.2 选择机制的解释 3.6 额外的模型细节A 讨论&#xff1a;选择机制C 选择SSM的机制 Mamba论文 第一部分 Mamba:选择状态空间模型的线性时间序列建模(一) 3.4 一个简化的SSM结构 如同结构SSM&#…

【笔记】ArkTS 语言(OpenHarmony系统)

一、官方简介和文档 介绍&#xff1a;aArkTS 语言 | 华为开发者联盟 (huawei.com) 学习指南&#xff08;文档&#xff09;&#xff1a;初识ArkTS语言-学习ArkTS语言-入门 | 华为开发者联盟 (huawei.com) 二、ArkTS语言知识 &#xff08;一&#xff09;编程语言介绍 Mozilla创…

对象变更记录objectlog工具(持续跟新)

文章目录 前言演示代码演示环境引入项目项目框架操作步骤 设计介绍参考仓库 前言 系统基于mybatis-plus, springboot环境 对于重要的一些数据&#xff0c;我们需要记录一条记录的所有版本变化过程&#xff0c;做到持续追踪&#xff0c;为后续问题追踪提供思路。下面展示预期效果…

蓝牙系列一:初识蓝牙

早就对蓝牙的知识垂涎已久&#xff0c;由于各种原因都没能系统的好好的学习一下&#xff08;最大的原因就是自己太懒了&#xff01;&#xff01;&#xff09;&#xff0c;最近有时间来系统的学一下蓝牙的知识。文章中很多都是通过学习韦东山老师的蓝牙讲解&#xff0c;讲得非常…

Excel技巧:如何对含有相同内容的列增加递增序号

如何在Excel中对含有相同内容的单元格自动添加递增序号 当我们在处理Excel数据时&#xff0c;经常会遇到需要根据某一列中的重复内容来对另一列的单元格进行编号的情况。例如&#xff0c;我们可能需要对所有含有特定字符的单元格进行标记&#xff0c;并在另一列中为它们分配一…

C语言项目实战——贪吃蛇

C语言实现贪吃蛇 前言一、 游戏背景二、游戏效果演示三、课程目标四、项目定位五、技术要点六、Win32 API介绍6.1 Win32 API6.2 控制台程序6.3 控制台屏幕上的坐标COORD6.4 GetStdHandle6.5 GetConsoleCursorInfo6.5.1 CONSOLE_CURSOR_INFO 6.6 SetConsoleCursorInfo6.7 SetCon…

2025汤家凤考研数学,基础视频课程+百度网盘+PDF真题讲解

平时大家都半开玩笑地讲&#xff1a;我数学想要考150分&#xff01;那索性今天这一期&#xff0c;今天认真和大家聊一下&#xff1a; 想考到考研数学150分&#xff0c;应该如何准备&#xff1f; 如果还有小伙伴不知道在哪看汤神的ke&#xff0c;可以看一下以下 2025汤神全程…