**vue2:**数据发生变化之后是生成一棵新的DOM树,然后就行全局对比。
如下图:
**vue3:**新增静态标记(Patch flag)在与上次的虚拟节点进行对比,只对比带有Patch flag的节点并且可以通过flag的信息得知当前节点要对比的具体内容
vue生成虚拟DOM网站
如图:
**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 */) ])) }默认情况下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算法中,只有有静态标记的才会进行比较,才会进行追踪
当有大量静态内容时候,这些内容会被当做纯字符串推进一个buffer里面,即使存在动态绑定,会通过模板插值嵌入进去。这样会比通过虚拟dom来渲染的快上很多很多。
当静态内容大到一定量级时候,会用_createStaticVNode方法在客户端生成一个static node,这些静态node,会被直接innerHTML,就不需要创建对象,然后根据对象渲染。
