当使用hoistStatic时,所有 静态的节点都被提升到render方法之外。这意味着,他们只会在应用启动的时候被创建一次,而后随着每次的渲染被不停地复用。
示例如下:
<div>
<p>你好p>
<p>{{userName}}p>
div>
// 静态提升
const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "你好", -1 /* HOISTED */)
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createBlock(_Fragment, null, [
_hoisted_1,
_createVNode("p", null, _toDisplayString(_ctx.userName), 1 /* TEXT */)
], 64 /* STABLE_FRAGMENT */))
}
在平时vue开发过程中,组件当中没有特别多的动态元素,大多都是静态元素。
一般可以说是动静比,动态内容 / 静态内容,比例越小,静态内容越多,比例越大,动态内容越多。
vue3的编译器它会非常智能地发现这一点,当编译器遇到大量连续的静态内容,会直接将它编译为一个普通字符串节点,因为它知道这些内容永远不会变化,都是静态节点。
注意:必须是大量连续的静态内容才可以预字符串化哦,切记!目前是连续20个静态节点才会预字符串化
<div>
<div>
<h1>法医h1>
div>
<p>...20...p>
div>
// 直接预字符串化,避免创建虚拟dom
const hoistStatic = createStatticVNode('法医
...20个...
')
render() {
return (openBlock(), createBlock('div', null, [hoistStatic]))
}
// vue2处理方式render(ctx){
return createVNode("button",{
onclick:function($event){
ctx.count++;
}
})
}
//vue3 处理方式render(ctx,_cache){
return createVNode("button",{
onclick:cache[0] || (cache[0] =>($event) =>(ctx.count++))
})
}
在vue2中创建一个虚拟节点button,属性里面多了一个事件onclick,内容就是count++。在vue3中会认为这里的事件处理是不会变化的,不是说这次渲染是事件函数,下次就变成别的,于是vue3会智能地发现这一点,会做缓存处理,它首先会看一看缓存里面有没有这个事件函数,有的话直接返回,没有的话就直接赋值为一个count++函数,保证事件处理函数只生成一次。
理解的不多
其实就是把那些DOM结构可能发生改变的地方也作为一个动态节点进行收集。
在之前的VDOM中,如果msg值发生改变,整个模版中的所有元素都需要重新渲染。但在Vue3.0中,在这个模版编译时,编译器会在动态标签末尾加上 /* Text*/ PatchFlag。只能带patchFlag 的 Node 才被认为是动态的元素,会被追踪属性的修改。并且 PatchFlag 会标识动态的属性类型有哪些,比如这里 的TEXT 表示只有节点中的文字是动态的。
每一个Block中的节点,就算很深,也是直接跟Block一层绑定的,可以直接跳转到动态节点而不需要逐个逐层遍历。
既有VDOM的灵活性,又有性能保证。
示例如下:
<div>
<p>测试内容p>
<p>测试内容p>
<p>{{msg}}p>
div>
// 表示类型
export const enum PatchFlags {
TEXT = 1,// 动态的文本节点
CLASS = 1 << 1, // 2 动态的 class
STYLE = 1 << 2, // 4 动态的 style
PROPS = 1 << 3, // 8 动态属性,不包括类名和样式
FULL_PROPS = 1 << 4, // 16 动态 key,当 key 变化时需要完整的 diff 算法做比较
HYDRATE_EVENTS = 1 << 5, // 32 表示带有事件监听器的节点
STABLE_FRAGMENT = 1 << 6, // 64 一个不会改变子节点顺序的 Fragment
KEYED_FRAGMENT = 1 << 7, // 128 带有 key 属性的 Fragment
UNKEYED_FRAGMENT = 1 << 8, // 256 子节点没有 key 的 Fragment
NEED_PATCH = 1 << 9, // 512
DYNAMIC_SLOTS = 1 << 10, // 动态 solt
HOISTED = -1, // 特殊标志是负整数表示永远不会用作 diff
BAIL = -2 // 一个特殊的标志,指代差异算法
}
export function render(_ctx, _cache) {
return (_openBlock(),
_createBlock('div',null,[
_createVNode('p',null,'测试内容'),
_createVNode('p',null,'测试内容'),
_createVNode('p',null,_toDisplayString(_ctx.msg),1 /**TEXT*/),
]
)
)
}