2.Vue3.0 性能提升主要是通过哪几方面体现的?
一、编译阶段
回顾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 具体的不同,我们下篇文章会进行一个更加详细的介绍
2.Vue3.0 性能提升主要是通过哪几方面体现的?相关推荐
- 面试官:Vue3.0 性能提升主要是通过哪几方面体现的?
一.编译阶段 回顾Vue2,我们知道每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把用到的数据property记录为依赖,当依赖发生改变,触发setter,则会通知watcher ...
- vue3性能提升主要是通过哪几方面体现的
一.Vue 3.0 性能提升主要是通过哪几方面体现的? 1. 响应式系统提升 vue2在初始化的时候,对data中的每个属性使用definepropery调用getter和setter使之变为响应式对 ...
- Nacos 2.0 性能提升十倍,贡献者 80% 以上来自阿里之外
来源 | 阿里巴巴云原生公众号 3 月 20 日,Nacos 2.0 正式发布.Nacos 是阿里巴巴在 2018 年开源的一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台,也可以理解为 ...
- 重磅官宣:Nacos2.0性能提升10倍
简介:Nacos2.0 作为一个跨代版本,彻底解决了 Nacos1.X 的性能问题,将性能提升了 10 倍. 作者:席翁 继 Nacos 1.0 发布以来,Nacos 迅速被成千上万家企业采用,并构 ...
- vue3.0性能优化点之静态标记(PatchFlag)
关注Vue3源码库的童鞋应该有注意到,2021.11月2号Vue更新到了3.2.21版本,自Vue3发布以来,一直在不断的迭代完善着,Vue3的GitHub仓库已有25.7k Star, 主流UI框 ...
- 华为P9怎么修改AGPS服务器,华为P9不需root,这样设置EMUI5.0性能提升2倍
近日,华为针对P9/P9Plus机型正式推送了EMUI5.0系统升级.这款在去年4月份上市的产品,至今已经在全球市场上拥有了超过千万的用户,这次华为手机为所有P9系列手机用户推送系统升级,可以让更多华 ...
- Vue3.0性能优化之toRaw,markRaw
有一些操作不需要更新UI界面,就可以用toRaw,节约性能,我们可以通过toRaw方法拿到它的原始数据,对原始数据进行修改,就不会更新UI界面 怎么做呢?先说下toRaw配合reactive impo ...
- 重磅官宣:Nacos2.0发布,性能提升10倍
简介: Nacos2.0 作为一个跨代版本,彻底解决了 Nacos1.X 的性能问题,将性能提升了 10 倍. 作者:席翁 继 Nacos 1.0 发布以来,Nacos 迅速被成千上万家企业采用,并 ...
- 学习Vue3.0笔记
Vue3.0快速上手 @[TOC](Vue3.0快速上手) Vue3简介 Vue3.0相对于Vue2多了些什么? 1.性能的提升 2.源码改变 3.拥抱TS 4.新特性(重点) 常用的组合式API V ...
最新文章
- VC++ 字符串操作学习总结
- c语言主范式与编码,超详细!终于搞明白KMP算法
- sqlserver 班级排名_Sqlserver:班级排名问题(转发)
- JavaScript --- 表单focus,blur,change事件的实现
- java 读取集合到流中_Java 10:将流收集到不可修改的集合中
- ubuntu18.04安装mysql8
- IIS HTTP文件服务器搭建步骤
- bio linux 创建_Linux 五种IO模型
- 2018Oracle11g下载与安装菜鸟教程(二)
- 基于DWM1000的UWB测距调试(二)
- linux pt远程下载,Linux中使用Transmission下载BT/PT[zz]
- 无PS只需几步操作轻松改变图片尺寸大小,而且一点都不失真!
- 中国茶道的基本精神(转)
- 计算机维护工具全能版,USBOS V3.0彪悍版
- mac电脑显示隐藏文件方法
- 五分钟看懂python函数(同Java方法作比较)
- (C++)将8000秒换算成小时分钟秒的形式
- C++ Reference: Standard C++ Library reference: C Library: cstdio: vsnprintf
- 归档数据1000份,筑智建助力融汇温泉城G1项目高效完成数字化落地
- 将Vue通过nginx部署到阿里云服务器上