El DOM: leer y cambiar la página
💡 🎯 Al terminar esta lección podrás…
- Seleccionar elementos con
querySelectoryquerySelectorAll. - Cambiar texto, clases, estilos y atributos de forma segura.
- Crear, añadir y eliminar elementos desde JavaScript.
- Evitar los errores más comunes con el DOM y el riesgo de
innerHTML.
1.Qué es el DOM
Cuando el navegador lee tu HTML, construye un árbol de objetos que representa la página: el DOM (*Document Object Model*). Cada etiqueta es un nodo de ese árbol, y JavaScript puede leerlo y modificarlo; cada cambio se refleja al instante en pantalla.
<body>
<h1 id="titulo">Hola</h1>
<ul>
<li>Uno</li>
<li>Dos</li>
</ul>
</body>
document
└── body
├── h1#titulo → "Hola"
└── ul
├── li → "Uno"
└── li → "Dos"
El objeto document es la puerta de entrada al DOM. Con él buscas elementos, y cada elemento es un objeto con propiedades (textContent, className…) y métodos (append(), remove()…).
📌 Nota · Los editores del curso
En esta lección cada editor tiene una Página (resultado) a la derecha. Tu script modifica esa página. Pulsa Ejecutar para volver a empezar con el HTML original.
2.Seleccionar elementos
| Método | Devuelve | Ejemplo |
|---|---|---|
document.getElementById("id") | Un elemento (o null) | getElementById("titulo") |
document.querySelector("css") | El primer elemento que coincide | querySelector(".caja"), querySelector("ul li") |
document.querySelectorAll("css") | Una lista de todos los que coinciden | querySelectorAll("li") |
elemento.closest("css") | El ancestro más cercano que coincide | boton.closest(".tarjeta") |
elemento.children | Los hijos directos |
Los selectores son los mismos del curso de CSS: #id, .clase, etiqueta, ul > li, [type="email"]… Si ya dominas CSS, ya sabes seleccionar.
⚠️ Importante · null si no existe
Si el selector no encuentra nada, getElementById y querySelector devuelven null, y usar null.textContent da el error *«Cannot read properties of null»*. Casi siempre es una errata en el selector o un script que se ejecuta antes de que el elemento exista (usa defer o pon el script al final).
3.Leer y cambiar el contenido
| Propiedad | Qué hace | Cuándo |
|---|---|---|
textContent | Lee o cambia el texto (sin interpretar HTML) | Casi siempre. Es seguro |
innerHTML | Lee o cambia el HTML interno | Solo con HTML propio y de confianza |
value | El valor de un input, select o textarea | Formularios |
outerHTML | El HTML del elemento incluido él mismo | Poco habitual |
⚠️ Importante · Seguridad: nunca innerHTML con datos de usuarios
Si insertas con innerHTML un texto que escribió alguien (un comentario, un nombre), esa persona puede colar código malicioso (ataque XSS). Con textContent el texto se muestra siempre como texto, sin riesgo. Regla: usa textContent por defecto, y innerHTML solo con HTML que tú escribiste.
4.Clases, estilos y atributos
| Quiero… | Uso |
|---|---|
| Añadir / quitar / alternar una clase | el.classList.add(), .remove(), .toggle() |
| Saber si tiene una clase | el.classList.contains() |
| Un estilo concreto | el.style.color = "red" |
| Leer / cambiar un atributo | getAttribute() / setAttribute() / removeAttribute() |
| Guardar datos en el HTML | el.dataset.nombre (atributos data-nombre) |
💡 Consejo · Cambia clases, no estilos
Mantén el aspecto en el CSS y desde JavaScript solo añade o quita clases: tarjeta.classList.toggle("activa"). Así separas las responsabilidades y tu CSS sigue mandando.
5.Crear, añadir y eliminar elementos
- Crea el elemento:
document.createElement("li"). - Dale contenido y atributos:
li.textContent = "…". - Añádelo a la página:
lista.append(li).
<li> y lo añade a la página.| Método | Qué hace |
|---|---|
padre.append(hijo) / prepend(hijo) | Añade al final / al principio |
elemento.before(x) / after(x) | Inserta antes / después del elemento |
elemento.remove() | Elimina el elemento |
elemento.replaceWith(x) | Lo sustituye por otro |
elemento.cloneNode(true) | Crea una copia (con sus hijos) |
padre.replaceChildren() | Vacía el contenedor (o lo reemplaza con lo que pases) |
6.Plantillas con HTML: cuándo sí usar innerHTML
Para estructuras con mucho HTML, crear cada elemento a mano es tedioso. Si los datos son tuyos (no de usuarios), puedes generar HTML con plantillas de texto:
⚠️ Importante · Datos propios
Esto es seguro solo porque los datos los escribimos nosotros. Si nombre viniera de un formulario o de internet, tendrías que escapar el texto o crear los elementos con createElement y textContent.
7.NodeList: una lista que no es un array
querySelectorAll devuelve una NodeList: se parece a un array (tiene length, se puede recorrer con for…of y forEach) pero no tiene map, filter ni reduce. Para usarlos, conviértela con Array.from() o el spread:
8.Errores frecuentes
- Script que se ejecuta antes de que exista el elemento:
null. Usadefero ponlo al final del<body>. - Errata en el selector:
#titulofrente a.titulofrente atitulo. - Usar
innerHTMLcon datos de usuario: riesgo de XSS. UsatextContent. - Esperar un array de
querySelectorAll: es una NodeList (sinmap). - Cambiar estilos con
styleen vez de clases: mezclas aspecto y lógica. - Escribir
elemento.style.font-size: en JavaScript se escribe en camelCase:fontSize. - Modificar el DOM dentro de un bucle muy grande: es lento; construye todo y añádelo una vez.
- Olvidar que
createElementno añade nada: hay queappendel elemento.
📒 Apuntes para llevar
- El DOM es el árbol de objetos que representa la página;
documentes su punto de entrada. - Selecciona con
getElementById,querySelector(uno) yquerySelectorAll(todos), con los mismos selectores de CSS; devuelvennullsi no encuentran. textContentcambia el texto de forma segura;innerHTMLinterpreta HTML y solo se usa con datos propios;valuelee los campos.classList.add/remove/toggle/containscambia el aspecto sin mezclar estilos;style,setAttributeydatasetcubren los demás casos.- Crea con
createElement, añade conappend/prepend/before/aftery elimina conremove(). querySelectorAlldevuelve una NodeList: usaArray.from()o[...]para tenermapyfilter.- Ejecuta tu script cuando la página esté lista (
defer). - Nunca insertes datos de usuarios con
innerHTML.
9.Glosario
| Término | Significado |
|---|---|
| DOM | Representación en forma de árbol de objetos de la página. |
| Nodo | Cada elemento, texto o comentario del árbol. |
| Selector | Texto (como en CSS) que identifica uno o varios elementos. |
textContent | Propiedad que lee o cambia el texto de un elemento. |
innerHTML | Propiedad que lee o cambia el HTML interno; peligrosa con datos de usuarios. |
classList | Objeto para añadir, quitar o alternar clases. |
| NodeList | Lista de nodos que devuelve querySelectorAll. |
| XSS | Ataque que inyecta código malicioso en una página. |
🧠 Comprueba lo aprendido
Elige una respuesta en cada pregunta. Verás al instante si acertaste y por qué.
¿Qué devuelve document.querySelector(".no-existe")?
Si no hay coincidencias devuelve null.
Quieres mostrar un comentario que escribió un usuario. ¿Qué usas?
textContent muestra siempre texto plano y evita ataques XSS.
¿Cuál es la forma recomendada de resaltar un elemento?
Manteniendo el aspecto en el CSS y alternando clases desde JavaScript.
document.querySelectorAll("li").map(...) da un error porque…
Convierte antes con Array.from() o [...lista].
¿Qué hace document.createElement("li") por sí solo?
Hay que añadirlo después con append o similar.
Tu progreso se guarda en este navegador y se refleja en el índice del curso.
💡 🚀 ¡Ahora te toca!
La práctica fija lo aprendido. Pasa al ejercicio de esta lección.