浅谈 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.hqwc.cn/news/513784.html

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

相关文章

Redis 缓存机制如何提高应用程序的性能?

在数字时代&#xff0c;一拍脑门儿我们就能感觉到信息的海量和处理速度的迫切。不管是刷个微博、下个单&#xff0c;还是玩个游戏&#xff0c;我们都希望能快上加快&#xff0c;一点不拖泥带水。这时候&#xff0c;缓存技术就扮演了个大英雄的角色&#xff0c;它能让数据存取的…

Mysql80服务无法启动请输入Net helpMsg3534以获得更多的帮助

起因&情景&#xff1a; 朋友正在操作数据库&#xff0c;然后电脑突然死机&#xff0c;再重启电脑后启动数据库服务报&#xff1a; 然后朋友尝试各种操作都没有办法正常启动&#xff0c; 一、网上解决方案&#xff1a;&#xff08;先别操作&#xff09; 1 删掉&#xff1a…

基于 HBase Phoenix 构建实时数仓(1)—— Hadoop HA 安装部署

目录 一、主机规划 二、环境准备 1. 启动 NTP 时钟同步 2. 修改 hosts 文件 3. 配置所有主机间 ssh 免密 4. 修改用户可打开文件数与进程数&#xff08;可选&#xff09; 三、安装 JDK 四、安装部署 Zookeeper 集群 1. 解压、配置环境变量 2. 创建配置文件 3. 创建新…

自动化测试基础——Pytest框架之YAML详解以及Parametrize数据驱动

文章目录 一、YAML详解1.YAML作用2.YAML语法结构3.YAML数据类型3.1.对象3.2.数组3.3.标量 4.YAML的引用5.YAML类型转换 二、YAML的读写与清空1.YAML的读2.YAML的写3.YAML的清空 三、pytest的parametrize简单数据驱动四、pytest的parametrize结合yaml实现数据驱动五、解决pytest…

SprinBoot集成nacos

环境搭建 采用docker-compose搭建测试环境 # docker-compose参考&#xff1a;https://github.com/nacos-group/nacos-docker/blob/master/example/standalone-mysql-5.7.yaml # Nacos文档&#xff1a;https://nacos.io/zh-cn/index.html version: 3# 网桥 -> 方便相互通讯 …

结合大象机器人六轴协作机械臂myCobot 280 ,解决特定的自动化任务和挑战!(上)

项目简介 本项目致力于探索和实现一种高度集成的机器人系统&#xff0c;旨在通过结合现代机器人操作系统&#xff08;ROS&#xff09;和先进的硬件组件&#xff0c;解决特定的自动化任务和挑战。一部分是基于Jetson Orin主板的LIMO PPRO SLAM雷达小车&#xff0c;它具备自主导航…

upload-Labs靶场“11-15”关通关教程

君衍. 一、第十一关 %00截断GET上传1、源码分析2、%00截断GET上传 二、第十二关 %00截断POST上传1、源码分析2、%00截断POST上传 三、第十三关 文件头检测绕过1、源码分析2、文件头检测绕过 四、第十四关 图片检测绕过上传1、源码分析2、图片马绕过上传 五、第十五关 图片检测绕…

PYQT5打包报错 FileNotFoundError ModuleNotFoundError:No Module named ‘MyImport‘

pyinstaller打包pyqt5程序得到exe文件无法运行的问题 在执行该命令之后pyinstaller -D -w main.py&#xff0c;生成的exe文件运行出现报错&#xff0c;ui文件找不到、模块找不到等&#xff0c;这些是因为程序使用到非官方库等问题&#xff0c;总之就是你自己的各种文件在代码中…

图像处理 mask掩膜

1&#xff0c;图像算术运算 图像的算术运算有很多种&#xff0c;比如两幅图像可以相加&#xff0c;相减&#xff0c;相乘&#xff0c;相除&#xff0c;位运算&#xff0c;平方根&#xff0c;对数&#xff0c;绝对值等&#xff1b;图像也可以放大&#xff0c;缩小&#xff0c;旋…

Git分布式管理-头歌实验分支管理

一、创建本地分支-git branch 任务描述 当你进入一个团队&#xff0c;在获得产品的完整代码之后&#xff0c;你首先要做的就是&#xff0c;在本地创建一个属于自己的分支&#xff0c;然后才能在自己的分支上进行开发。 本关任务&#xff1a;在本地仓库创建一个新的分支&#xf…

flutter小程序开发,Android高级工程师必备知识

AWTK 主要特色&#xff1a; 1、跨平台 AWTK 是跨平台的&#xff0c;这有两个方面的意思&#xff1a; AWTK 本身是跨平台的。目前支持的平台有 ZLG AWorks、Windows、Linux、MacOS、嵌入式 Linux、Android、Web 和嵌入式裸系统&#xff0c;可以轻松的移植到各种 RTOS 上。AWT…

javascript基础入门

1.第一个javascript程序 javascript程序不能够独立的运行&#xff0c;必须依赖于HTML文件&#xff0c;type属性值用来说明脚本的类型&#xff0c;这里 是指使用javascript编写的文本文件&#xff1b; 2.alert警告框 alert&#xff08;&#xff09;函数显示一条指定的信息&am…