Estimated reading time: 5 min read

All Roads Lead to DOM — How React and Vue See the Browser Differently

#framework#react.js#vue.js#scalable-ui#frontend-architecture#dom#reactivity

When developers talk about frontend frameworks, the conversation often turns into "React vs Vue". But beneath preferences and syntax lies something deeper: their approach to the DOM. Both frameworks abstract away direct DOM manipulation — yet how they *think about* the DOM, state, and rendering couldn't be more different. This post isn’t about choosing sides. It’s about understanding the two mental models that shape how your app connects to the browser.

The DOM Is Not Your Playground Anymore

In the early days of JavaScript, developers manually touched the DOM: selecting elements, injecting HTML, or changing text with innerHTML. That world was imperative — “find this element and do this to it.” React and Vue changed that. They introduced a declarative model: You no longer tell the browser *how* to change — you just declare *what* the UI should look like for a given state. The frameworks handle the rest.

React — Predictability Over Magic

React treats your UI like a pure function of state:

typescript
UI = f(state)

When something changes, React doesn’t surgically modify the DOM. Instead, it rebuilds a virtual DOM tree, compares it with the previous version, and applies the minimal set of DOM updates. This process is called reconciliation. You never mutate the DOM or the data directly. You call explicit state setters — for example:

jsx
const [count, setCount] = useState(0);
setCount(count + 1);

React re-renders the component, diffs it, and patches the DOM. This model is immutable: you don’t edit existing state; you replace it with a new one. That immutability makes rendering predictable — React always knows when to update because you explicitly told it to. Under the hood, React’s Fiber engine introduces *scheduling*. Rendering can pause, resume, or batch updates for performance. That’s why even in complex UIs, React feels responsive — it controls when the DOM updates happen, not the browser. In short: React doesn’t try to be smart about which variable changed. It simply re-renders, diffs, and trusts its scheduler.

Vue — Reactivity Over Explicitness

Vue approaches the same problem differently. Instead of waiting for you to call a setter, Vue tracks dependencies automatically. Every reactive variable is wrapped in a Proxy. When a value is read, Vue “tracks” it. When that value changes, Vue “triggers” exactly the components or DOM nodes that depend on it. For example:

vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">Clicked {{ count }} times</button>
</template>

When count++ runs, Vue’s reactivity system knows that only this text node uses count. It updates that part of the DOM directly — no diffing needed. This system makes features like v-model (two-way binding) possible. The data and DOM stay in sync automatically — a little bit of “magic,” powered by the Proxy. Vue favors mutability: you can change data directly, and Vue observes it. That gives you simplicity, but less explicit control over timing and scheduling.

Two Roads to the Same Browser

React and Vue both promise a world where you don’t manually touch the DOM. But their philosophies diverge at one question: Who should know what changed — the framework, or you? React says: *“You tell me what changed, and I’ll re-render predictably.”* Vue says: *“I’ll watch your data and react automatically.”* React gives developers predictability through immutability and controlled scheduling. Vue gives developers reactivity through automatic dependency tracking. Both approaches build virtual DOMs. Both aim to minimize DOM operations. But React does it through explicit re-renders, while Vue does it through automatic observation.

The Magic (and Responsibility)

When you use React, you take responsibility for *when* updates happen. When you use Vue, the framework takes responsibility for *what* updates happen. Neither is better — they simply reflect different philosophies about control, performance, and developer experience. The DOM is no longer a chaotic playground. It’s a *reactive canvas*, and each framework paints it with its own kind of magic.