Inicio / Artículos

Los nodos DOM no son la cadena HTML que enviaste.

El DOM no es la cadena de HTML que se envió. Los árboles de análisis, las listas Node en tiempo real y los reflows explican por qué el razonamiento a nivel de cadena falla en los frontends de JavaScript y React.

Editor: REACTAPP.TOP5 min de lectura1180 palabras

Fuentes: The DOM Is Not Your HTML: The Difference Every Frontend Developer Should Understand

Tú escribes el HTML, pero JavaScript nunca modifica ese archivo en el disco. En lugar de eso, interactúa con el Modelo de Objetos de Documento en tiempo real del navegador.

Cuando el marcado llega al navegador, se establece la estructura inicial de la página. Un documento puede comenzar con un encabezado simple:

<h1>Hello</h1>

Después de la carga, JavaScript puede localizar ese encabezado y reemplazar su texto:

document.querySelector("h1").textContent = "Hello World";

Luego la pantalla muestra:

<h1>Hello World</h1>

Puede parecer que el propio archivo HTML fue reescrito. Pero no es así; el archivo en el servidor sigue conteniendo el encabezado original. JavaScript modificó el modelo en tiempo real del navegador de la página, es decir, el DOM. Separar el marcado de origen de ese modelo en tiempo real aclara muchos comportamientos de JavaScript.

HTML es un documento. El DOM es una representación en tiempo real.

HTML es el marcado que tú creas, por ejemplo:

<body>
  <h1>Hello</h1>
  <button>Click me</button>
</body>

El navegador analiza ese documento y lo convierte en una estructura en memoria. Esa estructura es el Modelo de Objetos de Documento. Un esquema aproximado del proceso es el siguiente:

HTML
 │
 │ browser parses
 ▼
DOM
 │
 ├── body
 │    ├── h1
 │    └── button

El DOM no es simplemente una copia en forma de cadena del HTML. Es un documento estructurado y programable. Eso es lo que manipula JavaScript.

¿Entonces, qué cambia realmente JavaScript?

Comience con:

<h1 id="title">Hello</h1>

Luego ejecute:

const title = document.querySelector("#title");
title.textContent = "Welcome";

La script encuentra el nodo del DOM y actualiza su texto. El árbol en tiempo real ahora representa:

<h1 id="title">Welcome</h1>

El código HTML original no fue reescrito. Si el marcado provino de un servidor o de un archivo estático, esa fuente sigue conteniendo:

<h1 id="title">Hello</h1>

La diferencia es pequeña pero crucial: mutar el DOM no es lo mismo que editar el código HTML original.

Aquí hay una forma sencilla de ver la diferencia

Abra una página y cambie algo desde la consola:

document.querySelector("h1").textContent = "Changed!";

La página visible se actualiza de inmediato. Compare el DOM en tiempo real:

<h1>Changed!</h1>

con el código HTML original:

<h1>Hello</h1>

Pueden diferir porque el navegador trabaja con su DOM en tiempo real.

El DOM es más que lo que escribió originalmente

Supongamos que el marcado comienza así:

<ul id="users">
  <li>John</li>
</ul>

JavaScript puede añadir otro elemento:

const list = document.querySelector("#users");
const item = document.createElement("li");
item.textContent = "Sarah";
list.appendChild(item);

El árbol en tiempo real ahora contiene:

ul
├── li "John"
└── li "Sarah"

“Sarah” nunca apareció en el archivo original. El navegador no requiere un documento de origen reescrito; la script modificó el DOM en tiempo real. Esa capacidad es la base de los sitios interactivos.

El DOM es un árbol

“Modelo de objetos” suena más complejo de lo que en realidad es. En su forma más simple, el DOM es un árbol de nodos. Dado:

<main>
  <h1>Hello</h1>
  <p>Welcome!</p>
</main>

el navegador construye una estructura similar a esta:

Document
   │
   └── main
       ├── h1
       │    └── "Hello"
       │
       └── p
            └── "Welcome!"

Esa forma de árbol es la razón por la cual los scripts pueden recorrer relaciones como estas:

element.parentElement
element.children
element.nextElementSibling

No está escaneando un archivo de texto plano; está navegando por un árbol estructurado.

Y el DOM puede cambiar

El HTML de origen suele ser el documento inicial. El árbol en memoria permanece mutable durante la ejecución. Los scripts pueden asignar nodos:

const button = document.createElement("button");

establecer atributos:

button.setAttribute("disabled", "");

cambiar el contenido:

button.textContent = "Loading...";

y insertar el nodo:

document.body.append(button);

El árbol evoluciona mientras la aplicación está en ejecución, y por eso las interfaces interactivas no necesitan descargar todo el HTML cada vez que se produce un pequeño cambio.

Pero hay algo más que los desarrolladores a menudo confunden

Inspeccionar una página puede revelar HTML que nunca estuvo en el código fuente original. Los scripts pueden crear:

<div class="notification">
  Saved successfully
</div>

Usted no es el autor de ese nodo, pero DevTools puede mostrarlo en el panel Elements porque dicho panel refleja el DOM. Ver código fuente podría omitir completamente ese nodo.

Por lo tanto, no se garantiza que Ver código fuente e Inspeccionar elemento coincidan. Una razón común es que JavaScript modifique el DOM después de la carga inicial del HTML.

¿Por qué es importante esto para los desarrolladores front-end?

Mucho del comportamiento front-end se vuelve más claro una vez que el modelo mental cambia de “JavaScript modifica el HTML” a “JavaScript modifica el DOM”. Esa perspectiva explica APIs como:

element.classList.add("active");
element.remove();
element.textContent = "Loading...";
element.append(newElement);

Essas llamadas operan sobre la estructura del documento en tiempo real. El navegador luego utiliza ese árbol actualizado al dibujar la pantalla.

¿Y qué pasa con React?

Esa misma distinción es útil al aprender React. Puede que escriba:

return <h1>Hello</h1>;

JSX no es literalmente el DOM. Es una sintaxis que describe la interfaz de usuario. React decide cómo esa descripción debe reflejarse en el DOM real. Comprender el DOM antes de adentrarse en las abstracciones del framework hace que la renderización, la reconciliación, los referentes y las actualizaciones del DOM sean menos misteriosos.

No es necesario conocer cada detalle interno. Tenga en cuenta este proceso:

HTML
  ↓
Browser parses it
  ↓
DOM
  ↓
JavaScript can modify it
  ↓
Browser updates the rendered page

Los frameworks añaden capas adicionales, pero el DOM del navegador sigue siendo la base.

Un error común

A veces los desarrolladores tratan una mutación en el DOM como una edición permanente del HTML original. Pero no lo es. Por ejemplo:

document.body.innerHTML = "<h1>New page</h1>";

Esa asignación puede reemplazar la estructura actual en tiempo real, pero no vuelve a escribir el archivo HTML en el servidor. Una actualización recarga el documento desde su fuente. A menos que el cambio se haya persistido y se haya generado un nuevo HTML, vuelve a aparecer el documento original. Esa brecha separa el estado en tiempo de ejecución del contenido de origen.

El modelo mental que hay que recordar

Evite combinar las ideas de forma excesiva:

HTML = DOM

Prefiera un flujo similar a:

HTML
 │
 │ parsed by browser
 ▼
DOM
 │
 │ modified by JavaScript
 ▼
Updated DOM
 │
 │ used during rendering
 ▼
What the user sees

Trate el HTML como el documento de origen escrito por el autor. Trate el DOM como el árbol mutable del navegador construido a partir de ese origen. Los scripts modifican el árbol; la representación visual sigue lo que contiene actualmente el árbol.

Conclusión final

No equivoque el DOM con el archivo HTML. El marcado es lo que usted escribe; el modelo de objetos es lo que el navegador mantiene activo mientras la pestaña está abierta. Con esta separación, varios comportamientos se vuelven evidentes: por qué los scripts pueden agregar y eliminar nodos, por qué querySelector() funciona, por qué textContent actualiza lo que se ve, por qué las Herramientas de Desarrollo pueden mostrar nodos que usted nunca creó, por qué el árbol en tiempo real puede diferir del código fuente y por qué React, al final, sigue interactuando con el DOM.

El cambio útil es sencillo: usted escribe HTML, el navegador construye el DOM y JavaScript modifica el DOM. Una vez que esto queda claro, el DOM deja de parecerse a una API opaca y comienza a mostrarse tal como es: la representación en tiempo real de la página por parte del navegador.

Lecturas relacionadas