Rendering Mechanism
Virtual DOM
Section titled “Virtual DOM”const vnode = { type: 'div', props: { id: 'hello' }, children: [ /* more vnodes */ ]}Render Pipeline
Section titled “Render Pipeline”Vue’s rendering pipeline when mounting a component:
- Compile: Vue templates are compiled into render functions that return Virtual DOM trees.
- Mount: The render function is called to create VNodes, which are then used to create actual DOM nodes.
- Patch: When a component’s state changes, the render function is called again to create a new VNode tree. Vue then performs a “patch” operation between the old and new VNode trees to update the DOM efficiently.
Template Compilation Optimization
Section titled “Template Compilation Optimization”Vue performs optimizations during template compilation to improve runtime performance:
Hoisting Static Trees
Section titled “Hoisting Static Trees”<div> <div>foo</div> <!-- cached --> <div>bar</div> <!-- cached --> <div>{{ dynamic }}</div></div>Static sub-trees are hoisted and reused during re-renders.
Patch Flags
Section titled “Patch Flags”Vue marks VNodes with patch flags to indicate which parts of the DOM need to be updated:
<!-- class binding only --><div :class="{ active }"></div>
<!-- id and value bindings only --><input :id="id" :value="value">
<!-- text children only --><div>{{ dynamic }}</div>This results in compiled code like:
createElementVNode("div", { class: _normalizeClass({ active: _ctx.active })}, null, 2 /* CLASS */)The patch flag 2 indicates only the class needs to be updated:
if (vnode.patchFlag & PatchFlags.CLASS /* 2 */) { // update the element's class}Block Tree
Section titled “Block Tree”Vue uses a block tree structure to track dynamic nodes:
export function render() { return (_openBlock(), _createElementBlock(_Fragment, null, [ /* children */ ], 64 /* STABLE_FRAGMENT */))}Block tree example:
<div> <!-- root block --> <div>...</div> <!-- not tracked --> <div :id="id"></div> <!-- tracked --> <div> <!-- not tracked --> <div>{{ bar }}</div> <!-- tracked --> </div></div>This creates a block structure:
div (block root)- div with :id binding- div with {{ bar }} bindingSpecial handling for v-if and v-for:
<div> <!-- root block --> <div> <div v-if> <!-- if block --> ... </div> </div></div>The block tree allows Vue to efficiently skip static content and only update dynamic nodes during re-renders.