一、编译阶段

回顾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算法优化

vue3diff算法中相比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>`)
}

二、源码体积

相比Vue2Vue3整体体积变小了,除了移出一些不常用的API,再重要的是Tree shanking

任何一个函数,如refreavtivedcomputed等,仅仅在用到的时候才打包,没用到的模块都被摇掉,打包的整体体积变小

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来劫持整个对象,然后进行深度遍历所有属性,给每个属性添加gettersetter,实现响应式

vue3采用proxy重写了响应式系统,因为proxy可以对整个对象进行监听,所以不需要深度遍历

  • 可以监听动态属性的添加

  • 可以监听到数组的索引和数组length属性

  • 可以监听删除属性

关于这两个 API 具体的不同,我们下篇文章会进行一个更加详细的介绍

2.Vue3.0 性能提升主要是通过哪几方面体现的?相关推荐

  1. 面试官:Vue3.0 性能提升主要是通过哪几方面体现的?

    一.编译阶段 回顾Vue2,我们知道每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把用到的数据property记录为依赖,当依赖发生改变,触发setter,则会通知watcher ...

  2. vue3性能提升主要是通过哪几方面体现的

    一.Vue 3.0 性能提升主要是通过哪几方面体现的? 1. 响应式系统提升 vue2在初始化的时候,对data中的每个属性使用definepropery调用getter和setter使之变为响应式对 ...

  3. Nacos 2.0 性能提升十倍,贡献者 80% 以上来自阿里之外

    来源 | 阿里巴巴云原生公众号 3 月 20 日,Nacos 2.0 正式发布.Nacos 是阿里巴巴在 2018 年开源的一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台,也可以理解为 ...

  4. 重磅官宣:Nacos2.0性能提升10倍

    简介:​Nacos2.0 作为一个跨代版本,彻底解决了 Nacos1.X 的性能问题,将性能提升了 10 倍. 作者:席翁 继 Nacos 1.0 发布以来,Nacos 迅速被成千上万家企业采用,并构 ...

  5. vue3.0性能优化点之静态标记(PatchFlag)

    关注Vue3源码库的童鞋应该有注意到,2021.11月2号Vue更新到了3.2.21版本,自Vue3发布以来,一直在不断的迭代完善着,Vue3的GitHub仓库已有25.7k Star,  主流UI框 ...

  6. 华为P9怎么修改AGPS服务器,华为P9不需root,这样设置EMUI5.0性能提升2倍

    近日,华为针对P9/P9Plus机型正式推送了EMUI5.0系统升级.这款在去年4月份上市的产品,至今已经在全球市场上拥有了超过千万的用户,这次华为手机为所有P9系列手机用户推送系统升级,可以让更多华 ...

  7. Vue3.0性能优化之toRaw,markRaw

    有一些操作不需要更新UI界面,就可以用toRaw,节约性能,我们可以通过toRaw方法拿到它的原始数据,对原始数据进行修改,就不会更新UI界面 怎么做呢?先说下toRaw配合reactive impo ...

  8. 重磅官宣:Nacos2.0发布,性能提升10倍

    简介: ​Nacos2.0 作为一个跨代版本,彻底解决了 Nacos1.X 的性能问题,将性能提升了 10 倍. 作者:席翁 继 Nacos 1.0 发布以来,Nacos 迅速被成千上万家企业采用,并 ...

  9. 学习Vue3.0笔记

    Vue3.0快速上手 @[TOC](Vue3.0快速上手) Vue3简介 Vue3.0相对于Vue2多了些什么? 1.性能的提升 2.源码改变 3.拥抱TS 4.新特性(重点) 常用的组合式API V ...

最新文章

  1. VC++ 字符串操作学习总结
  2. c语言主范式与编码,超详细!终于搞明白KMP算法
  3. sqlserver 班级排名_Sqlserver:班级排名问题(转发)
  4. JavaScript --- 表单focus,blur,change事件的实现
  5. java 读取集合到流中_Java 10:将流收集到不可修改的集合中
  6. ubuntu18.04安装mysql8
  7. IIS HTTP文件服务器搭建步骤
  8. bio linux 创建_Linux 五种IO模型
  9. 2018Oracle11g下载与安装菜鸟教程(二)
  10. 基于DWM1000的UWB测距调试(二)
  11. linux pt远程下载,Linux中使用Transmission下载BT/PT[zz]
  12. 无PS只需几步操作轻松改变图片尺寸大小,而且一点都不失真!
  13. 中国茶道的基本精神(转)
  14. 计算机维护工具全能版,USBOS V3.0彪悍版
  15. mac电脑显示隐藏文件方法
  16. 五分钟看懂python函数(同Java方法作比较)
  17. (C++)将8000秒换算成小时分钟秒的形式
  18. C++ Reference: Standard C++ Library reference: C Library: cstdio: vsnprintf
  19. 归档数据1000份,筑智建助力融汇温泉城G1项目高效完成数字化落地
  20. 将Vue通过nginx部署到阿里云服务器上

热门文章

  1. LGA1155、LGA1156、LGA1366、LGA2011的CPU插槽对应的都是什么型号的CPU
  2. (Django)Web网页导入pycharm时遇到的问题集合(备份)
  3. SQL 中文首字母提取与自定义排序
  4. 开淘宝店怎么注册公司?开淘宝店是否需要去工商局登记注册公司
  5. nacos的命名空间
  6. Cent OS 7.4 1708 下载安装
  7. POI事件模式读取Excel 2003文件
  8. 想要报考华为技术认证,你一定要了解这些
  9. php 英文替换中文,php如何中英文符号替换?
  10. “嫦娥一号”可以证明美国当年登月是否属实