---
title: Understand How v-if and v-for Create New VDOM Blocks
impact: LOW
impactDescription: Vue's block-based optimization means conditional and loop structures create separate optimization boundaries
type: concept
tags: [vue3, rendering, vdom, v-if, v-for, blocks, internals]
---
# Understand How v-if and v-for Create New VDOM Blocks
**Impact: LOW** - This is an informational concept about Vue internals. Understanding blocks helps you reason about rendering performance, but Vue handles this automatically.
Vue's compiler creates "blocks" - template sections with stable structure. Block boundaries are created at `v-if` and `v-for` directives, where the inner structure can vary at runtime.
## Key Concepts
### What is a Block?
A block is a template section that:
1. Has a stable internal structure (same element types, same nesting)
2. Tracks only its dynamic descendant nodes (not all descendants)
3. Creates a flattened array for efficient reconciliation
### Block Boundaries
New blocks are created at:
- **Root of each component template**
- **`v-if` / `v-else` / `v-else-if`** - different branches may have different structures
- **`v-for`** - each iteration may differ
```vue
{{ message }}
{{ detail1 }}
{{ detail2 }}
{{ item.name }}
```
### How Blocks Optimize Rendering
Without blocks (pure runtime diffing):
```
Re-render walks ENTIRE tree:
div
header (check)
"Static Header" (check)
p (check)
message (check)
section (check)
span (check)
span (check)
div*N (check each)
span*N (check each)
footer (check)
"Static Footer" (check)
```
With blocks (Vue's approach):
```
Re-render only walks dynamic nodes:
Root block:
- p with {{ message }}
- v-if block reference
- v-for block references
v-if block (only if visible):
- span with {{ detail1 }}
- span with {{ detail2 }}
Each v-for block:
- span with :class and {{ item.name }}
```
## Why This Matters
1. **Static content is skipped**: Headers, footers, and unchanged elements are never traversed during updates
2. **Efficient list updates**: When a list item changes, Vue only diffs that item's block, not the entire list
3. **Branch switching is optimized**: When `v-if` toggles, Vue knows to replace the entire block rather than diffing incompatible structures
## Block Tracking Example
```vue
{{ title }}
{{ post.title }}
{{ post.excerpt }}
```
When `posts[2].title` changes:
- Vue finds the 3rd v-for block
- Diffs only that block's tracked dynamic nodes
- Skips all other posts, the nav, the aside
## You Don't Need to Do Anything
This optimization is automatic when using templates. Understanding blocks helps you:
- Reason about why updates are fast
- Understand Vue DevTools performance panel output
- Appreciate why templates are recommended over render functions
## Reference
- [Vue.js Rendering Mechanism - Tree Flattening](https://vuejs.org/guide/extras/rendering-mechanism.html#tree-flattening)
- [Vue.js Rendering Mechanism - Compiler-Informed Virtual DOM](https://vuejs.org/guide/extras/rendering-mechanism.html#compiler-informed-virtual-dom)