- Vue2.0 中的虚拟Dom是全量的对比
- Vue3.0 中新增了静态标记(PatchFlag)
在与上次的虚拟节点进行对比的时候,只对比带有patch flag的节点
并且可以通过flag的信息知道对比的内容
-
静态标记
Vue3 中仅对静态标记标记对象进行比较。
<div> <p>wzl</p> <p>wzl</p> <p>wzl</p> <p>{{msg}}</p> </div>
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, "wzl"), _createVNode("p", null, "wzl"), _createVNode("p", null, "wzl"), _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */) ])) }
可以看到,源码中,对 msg 设计了静态标记,这里是1,后面跟注释 TEXT ,代表这个标签的 TEXT 数据是会动态变化的。
-
hoistStatic静态提升
- Vue2中无论元素是否参与更新,每次都会重新创建然后渲染
- Vue3中对不参与的更新元素会做静态提升,只会被创建一次,在渲染时直接引用
/*
静态提升之前
*/
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, "111"),
_createVNode("p", null, "222"),
_createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */),
_createVNode("p", null, "333")
]))
}
/*
静态提升之后
不参与的更新元素会做静态提升,只会被创建一次,在渲染时直接引用
*/
import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"
const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "111", -1 /* HOISTED */)
const _hoisted_2 = /*#__PURE__*/_createVNode("p", null, "222", -1 /* HOISTED */)
const _hoisted_3 = /*#__PURE__*/_createVNode("p", null, "333", -1 /* HOISTED */)
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createBlock("div", null, [
_hoisted_1,
_hoisted_2,
_createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */),
_hoisted_3
]))
/*
开启事件侦听器缓存之前
*/
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createBlock("div", null, [
_createVNode("button", { onClick: _ctx.onClick }, null, 8 /* PROPS */, ["onClick"])
]))
}
/*
开启事件侦听器缓存之后
*/
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)))
})
]))
}
_createVnode 的第二个属性,从
{ onClick: _ctx.onClick }
变为了
{ onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick(...args))) }
它的意思很明显,onClick 方法被存入 cache。在使用的时候,如果能在缓存中找到这个方法,那么它将直接被使用。如果找不到,那么将这个方法注入缓存。总之,就是把方法给缓存了。
例如:
<div>
<button @click="onClick" @mouseover="onMouseover">btn</button>
<button @click="onClick1">btn</button>
</div>
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))),
onMouseover: _cache[2] || (_cache[2] = (...args) => (_ctx.onMouseover(...args)))
}, "btn", 32 /* HYDRATE_EVENTS */),
_createVNode("button", {
onClick: _cache[3] || (_cache[3] = (...args) => (_ctx.onClick1(...args)))
}, "btn")
]))
}