How does Vue interpolate reactive state into the DOM?

MediumIntermediateVue
Preparing for interviews?

Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.

Quick Answer

Explain what happens from a template expression like {{ count }} to a real DOM text node update: template compilation, dependency tracking during render, scheduling/batching, and DOM patching. Mention how Vue handles refs in templates and why interpolation escapes HTML by default.

Answer

The core idea

Vue doesn’t “re-run the whole DOM.” It compiles {{ ... }} into a render function that creates a Virtual DOM (VNode) tree. During render, Vue tracks which reactive properties were read. When one of those properties changes, Vue schedules the component update, re-runs the render function, diffs old vs new VNodes, and patches only the affected DOM nodes (e.g., a single text node).

Stage

What Vue does

Why it matters

1) Compile template

{{ count }} becomes code that produces a text VNode (via toDisplayString(count)).

Interpolation is not “magic at runtime”; it’s mostly compiler output + runtime patching.

2) Mount (first render)

Runs render inside a reactive effect. Any reactive read (like count) is tracked.

Vue learns exactly which component depends on which reactive keys.

3) State change

When you mutate reactive state, Vue triggers the dependent render effect(s).

Only components that used that state are scheduled to update.

4) Batch + schedule

Updates are queued/deduped and flushed in a microtask.

Multiple sync mutations typically lead to one DOM patch per component.

5) Patch DOM

Re-render → new VNodes → diff/patch updates only the dynamic parts (often a single text node).

Efficient updates without manual DOM manipulation.

Template interpolation → reactive update → DOM patch
HTML
<script setup>
import { ref, nextTick } from 'vue';

const count = ref(0);

async function incTwice() {
  count.value++;
  count.value++;

  // DOM is patched after the batched flush
  await nextTick();
  // Now the DOM reflects the final value
}
</script>

<template>
  <!-- Note: refs are auto-unwrapped in templates -->
  <p>Count: {{ count }}</p>
  <button @click="incTwice">+2</button>
</template>
                  

What the compiler roughly generates

Vue compiles templates to a render function that produces VNodes. For a dynamic text binding, the runtime can optimize patching using compiler hints (e.g., patch flags). Exact output varies, but the shape looks like this:

JAVASCRIPT
// Pseudo-ish compiled shape (not exact Vue output)
import { openBlock, createElementBlock, toDisplayString } from 'vue';

export function render(_ctx) {
  return (
    openBlock(),
    createElementBlock(
      'p',
      null,
      'Count: ' + toDisplayString(_ctx.count),
      /* patchFlag */ 1 // TEXT (runtime knows only text needs updating)
    )
  );
}
                  

Security: interpolation escapes HTML

{{ value }} renders text content (escaped). If you need to render HTML, Vue provides v-html, but you must treat it as XSS-sensitive and only use trusted/sanitized content.

HTML
<template>
  <!-- Escaped: renders literally as "<strong>Hi</strong>" -->
  <p>{{ raw }}</p>

  <!-- Not escaped: injects HTML into the DOM (danger if untrusted) -->
  <p v-html="raw"></p>
</template>

<script setup>
import { ref } from 'vue';
const raw = ref('<strong>Hi</strong>');
</script>
                  

Interview-ready takeaway

Interpolation in Vue is: template compile → render effect tracks reactive reads → state writes trigger scheduled re-render → VDOM diff + patch updates only the dynamic DOM nodes. Templates auto-unwrap refs, and interpolation is HTML-escaped by default.

Similar questions
Guides
9 / 34