Vue3.0快在哪儿?

it2026-04-06  5

Vue3.0快在哪儿?

一.diff算法的优化

**vue2:**数据发生变化之后是生成一棵新的DOM树,然后就行全局对比。

如下图:

**vue3:**新增静态标记(Patch flag)在与上次的虚拟节点进行对比,只对比带有Patch flag的节点并且可以通过flag的信息得知当前节点要对比的具体内容

vue生成虚拟DOM网站

如图:

附录Patch Flags
export const enum PatchFlags { TEXT = 1,//动态文本节点 CLASS = 1 << 1,//动态class STYLE = 1 << 2,//动态style PROPS = 1 << 3,//动态属性 FULL_PROPS = 1 << 4,//具有动态key属性 HYDRATE_EVENTS = 1 << 5,//带有监听事件的节点 STABLE_FRAGMENT = 1 << 6, //一个不会改变子节点顺序的fragment KEYED_FRAGMENT = 1 << 7, //带有key属性的fragment或者部分子字节有key UNKEYED_FRAGMENT = 1 << 8, //子节点没有key的fragment NEED_PATCH = 1 << 9, //一个节点只会进行非props比较 DYNAMIC_SLOTS = 1 << 10, //动态插槽 HOISTED = -1, //静态节点 BAIL = -2 //提示在diff过程应该退出优化模式 }

二.静态提升(hoist static)

**Vue2:**中无论元素是否参与更新,每次都会重新创建,然后再渲染

**Vue3:**中对于不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用即可

demo

<div> <p>我是段落</p> <p>{{msg}}</p> </div>

vue2.0静态提升前

import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue" export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("p", null, "我是段落"), _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */) ])) }

vue3.0静态提升后

import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue" //生成静态节点 const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "我是段落", -1 /* HOISTED */) //动态节点 export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _hoisted_1,//静态节点复用 _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */) ])) }

三.事件侦听器缓存(cache handlers)

默认情况下onClick会被视为动态绑定,所以每次都会去追踪它的变化但是因为是同一个函数,所以没有追踪变化,直接缓存起来复用即可

demo

<div> <button @click="onClick">按钮</button> </div>

vue2.0缓存之前

import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from "vue" export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("button", { onClick: _ctx.onClick }, "按钮", 8 /* PROPS */, ["onClick"]) ]))//UNKEYED_FRAGMENT = 1 << 8:有静态标记当做动态属性每次更新进行对比 }

vue3.0缓存之后

import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from "vue" 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))) }, "按钮") ]))//没有了静态标记不会更新后在进行对比 }

**注意点:**转换之后的代码,大家可能还看不懂,但是不要紧,我们只需要观察有没有静态标记即可,因为我们知道在Vue3的diff算法中,只有有静态标记的才会进行比较,才会进行追踪

四.ssr渲染(服务器端渲染)

当有大量静态内容时候,这些内容会被当做纯字符串推进一个buffer里面,即使存在动态绑定,会通过模板插值嵌入进去。这样会比通过虚拟dom来渲染的快上很多很多。

当静态内容大到一定量级时候,会用_createStaticVNode方法在客户端生成一个static node,这些静态node,会被直接innerHTML,就不需要创建对象,然后根据对象渲染。

最新回复(0)