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

news2024/11/18 8:27:09

前言

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

静态类型(前置信息)

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

export const enum PatchFlags {
  TEXT = 1,			// 动态的文本节点
  CLASS = 1 << 1,  // 2 动态的 class
  STYLE = 1 << 2,  // 4 动态的 style
  PROPS = 1 << 3,  // 8 动态属性,不包括类名和样式
  FULL_PROPS = 1 << 4,  		// 16 动态 key,当 key 变化时需要完整的 diff 算法做比较
  HYDRATE_EVENTS = 1 << 5,  	// 32 表示带有事件监听器的节点
  STABLE_FRAGMENT = 1 << 6,   	// 64 一个不会改变子节点顺序的 Fragment
  KEYED_FRAGMENT = 1 << 7, 		// 128 带有 key 属性的 Fragment
  UNKEYED_FRAGMENT = 1 << 8, 	// 256 子节点没有 key 的 Fragment
  NEED_PATCH = 1 << 9,   		// 512
  DYNAMIC_SLOTS = 1 << 10,  	// 动态 solt
  HOISTED = -1,  	// 特殊标志是负整数表示永远不会用作 diff
  BAIL = -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()) // 开始时间 1709628094030
    for (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()) // 1709627967983
    const 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.coloradmin.cn/o/1492379.html

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

相关文章

机器学习的魔法(二)超越预测的界限-揭秘机器学习的黑科技-探索监督学习中的回归和分类问题

前面我们提到了监督学习的概念&#xff0c;现在我们来回顾一下&#xff0c;什么是监督学习。 监督学习指的是&#xff1a;我们给学习算法一个数据集&#xff0c;这个数据集由正确答案组合而成&#xff0c;然后机器运用学习算法&#xff0c;算出更多的正确答案。 1、监督学习之…

GIS之深度学习07:CUDNN教程(CUDA12.1配套)

CUDNN&#xff08;CUDA Deep Neural Network library&#xff09;是NVIDIA专门针对深度学习应用开发的GPU加速库。它提供了一系列高效的深度学习算法的实现&#xff0c;包括卷积神经网络&#xff08;CNN&#xff09;、循环神经网络&#xff08;RNN&#xff09;等常用网络结构的…

QT----QTcreater连接Mysql数据库

目录 1、下载驱动&#xff0c;放入文件夹2、编写代码&#xff0c;实现本地访问3、实现网络数据库3.1 更改权限3.2 修改代码 之前写了一个图书管理系统用的是sqlite3&#xff0c;现在想用mysql&#xff0c;部署到网上&#xff0c;实现远程访问。 1、下载驱动&#xff0c;放入文…

VR虚拟生态探索介绍|元宇宙文旅|VR设备价格

虚拟现实&#xff08;VR&#xff09;虚拟生态探索是一种通过VR技术让用户体验并探索虚拟环境的活动。在这样的环境中&#xff0c;用户可以通过头戴式显示器和其他感知设备沉浸在一个虚拟的世界中&#xff0c;仿佛身临其境。 在VR虚拟生态探索中&#xff0c;用户可以探索各种不同…

IDEA中如何配置多个版本的JDK

1.首先创建一个Project. 2.点击菜单栏中的File,而后选择Project Structure. 3.进入该界面后点击SDK选择想要选择的jdk版本。 4.如果提供的jdk版本没有自己想要的&#xff0c;就点击ADD SDK,点击DownLoad JDK; 5.在弹出的窗口选择jdk的版本和想要下载到的位置。 6.下载成功…

Mysql删除重复项:力扣196. 删除重复的电子邮箱

题目链接&#xff1a;196. 删除重复的电子邮箱 - 力扣&#xff08;LeetCode&#xff09; 题目描述 sql语句 # Write your MySQL query statement below delete a from person as a inner join person as b where a.email b.email and a.id > b.id 思路&#xff1a;内连接…

Spring事件发布监听器ApplicationListener原理- 观察者模式

据说监听器模式也是mq实现的原理, 不过mq我还没来得及深入学习, 先用spring来理解一下吧 Spring事件发布监听器ApplicationListener原理- 观察者模式 什么是观察者模式一个Demo深入认识一下观察者模式Spring中的事件发布监听ps 什么是观察者模式 大家都听过一个故事叫做烽火戏…

GPT-4 及更高版本:大型语言模型的力量

GPT-4革命&#xff1a;人工智能如何重塑SEO行业 在人工智能领域&#xff0c;GPT-4 等语言模型的演变标志着一个重要的里程碑。 本文深入探讨了 GPT-4 的功能和潜力&#xff0c;同时也思考了人工智能领域的未来。 GPT-4 的出现&#xff1a;人工智能的新时代OpenAI 开发的 GPT-4…

MySQL 缓存策略

MySQL 缓存方案用来干什么 ? 缓存用户定义的热点数据&#xff0c;用户直接从缓存中获取热点数据&#xff0c;降低数据的读写压力。场景分析 内存访问速度是磁盘访问速度的 10 万倍。读的需求远远大于写的需求MySQL 自身缓冲层跟业务无关。MySQL 作为项目主要数据库&#xff0…

idea:springboot项目搭建

目录 一、创建项目 1、File → New → Project 2、Spring Initializr → Next 3、填写信息 → Next 4、web → Spring Web → Next 5、填写信息 → Finish 6、处理配置不合理内容 7、注意事项 7.1 有依赖包&#xff0c;却显示找不到依赖&#xff0c;刷新一下maven 二…

word转PDF的方法 简介快速

在现代办公环境中&#xff0c;文档格式转换已成为一项常见且重要的任务。其中&#xff0c;将Word文档转换为PDF格式的需求尤为突出&#xff0c;将Word文档转换为PDF格式具有多方面的优势和应用场景。无论是为了提高文档的可读性和稳定性、保障文档的安全性和保护机制、还是为了…

赛力斯造车引入强援,原华为智选车产品部部长加盟,任集团副总裁

作者 |德新 编辑 |王博 HiEV从多个信息源获悉&#xff0c;赛力斯造车近日引入一位业界大牛。原华为智选车产品部部长李博已于近日加盟&#xff0c;出任赛力斯集团副总裁。 李博是服役华为多年的老将&#xff0c;长期供职于华为终端生态。在华为体系中&#xff0c;产品部部长相…

Java基础数据结构之队列

一.什么是队列 队列是一种先进先出的数据结构&#xff0c;也就是从左边进从右边出&#xff0c;或者说&#xff0c;只允许在一端插入元素&#xff0c;在另一端删除元素 进行插入操作的一端称为队尾&#xff08;tail/rear&#xff09;&#xff0c;删除操作的一段称为队头&#…

MyBatis源码分析之基础支持层异常模块

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨ &#x1f440;&#x1f440;&#x1f440; 个人博客&#xff1a;小奥的博客 &#x1f44d;&#x1f44d;&#x1f44d;&#xff1a;个人CSDN ⭐️⭐️⭐️&#xff1a;传送门 &#x1f379; 本人24应届生一枚&#xff0c;技术和水平有限&am…

mac版本的vscode如何运行html文件

1.安装Live Server扩展 需在VS中安装一个拓展插件Live Server&#xff0c;插件寻找方法如下&#xff1a; 2.编写HTML文件 3.启动Live Server 在VSCode中打开你的HTML文件&#xff0c;并点击右键选择"Open with Live Server"&#xff0c;或者点击右下角的"Go…

安卓类加载机制

目录 一、ClassLoader介绍二、双亲委托机制三、类的加载过程 一、ClassLoader介绍 任何一个 Java 程序都是由一个或多个 class 文件组成&#xff0c;在程序运行时&#xff0c;需要将 class 文件加载到 JVM 中才可以使用&#xff0c;负责加载这些 class 文件的就是 Java 的类加…

Apache POI处理Miscrosoft Office 各种文件格式的开源项目

介绍: 应用场景 maven 坐标 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.16</version></dependency><dependency><groupId>org.apache.poi</groupId><artifa…

支付宝小程序模板开发,实现代小程序备案申请

大家好&#xff0c;我是小悟 支付宝小程序备案整体流程总共分为五个环节&#xff1a;备案信息填写、平台初审、工信部短信核验、通管局审核和备案成功。 服务商可以代小程序发起备案申请。在申请小程序备案之前&#xff0c;需要确保小程序基本信息已填写完成、小程序至少存在一…

Java_优先级队列(堆)(Priority Queue)

文章目录 一、优先级队列1.概念 二、优先级队列的模拟1.堆的概念2.堆的存储方式3.堆的创建1、堆向下调整2、堆的创建代码实现3、建堆的时间复杂度 2.堆的插入与删除1、堆的插入2、堆的删除3、完整的堆代码4、练习 一、PriorityQueue常用接口介绍1.PriorityQueue的特性2.Priorit…

Java项目:38 springboot005学生心理咨询评估系统

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 学生心理咨询评估系统有管理员和用户 【主要功能】 用户管理、试题管理、试卷管理、考试管理 【技术组成】 SpringBoot MyBatis Vue Boots…