17.4 预字符串化
在静态提升的基础上,把大段连续的静态节点直接序列化成 HTML 字符串,用一个
Static类型的 VNode 承载,创建与内存开销进一步下降。
一、静态提升的产物
<div>
<p></p>
<p></p>
<!-- ... 20 个 p 标签 -->
<p></p>
</div>
采用静态提升后编译结果大致如下——20 个静态节点变成 20 个变量:
const hoist1 = createVNode('p', null, null, PatchFlags.HOISTED)
const hoist2 = createVNode('p', null, null, PatchFlags.HOISTED)
// ... 20 个 hoistx 变量
const hoist20 = createVNode('p', null, null, PatchFlags.HOISTED)
function render() {
return (openBlock(), createBlock('div', null, [
hoist1, hoist2, /* ...20 个变量 */, hoist20,
]))
}
虽然静态节点不再重复创建,但仍要创建 20 个虚拟节点对象、占用对应内存。
二、预字符串化后
编译器把这些静态节点序列化为字符串,并生成一个 Static 类型的 VNode:
const hoistStatic = createStaticVNode('<p></p><p></p>...20 个...<p></p>')
function render() {
return (openBlock(), createBlock('div', null, [hoistStatic]))
}
20 个虚拟节点被压缩成 1 个 Static 类型 VNode;渲染时用 innerHTML 一次性把字符串写入 DOM。
三、好处
- 大块静态内容通过
innerHTML设置,在性能上有优势; - 减少创建虚拟节点带来的性能开销;
- 减少内存占用。
触发条件是「大段连续的静态节点」,节点太少时序列化字符串反而得不偿失,此时仍走静态提升。
相关
- 17.3 静态提升:预字符串化的前置优化
- 17.5 缓存内联事件处理函数:另一类避免无用更新的编译优化