Recopilación de ejercicios DOM JavaScript 3

¿Alguna vez te has preguntado cómo las páginas web modernas cobran vida, reaccionando a tus clics, mostrando contenido dinámico o adaptándose a tus interacciones? La magia detrás de todo esto reside en el Document Object Model (DOM) y la forma en que JavaScript lo manipula. Si eres un desarrollador web o aspiras a serlo, comprender y dominar la manipulación del DOM es una habilidad fundamental e imprescindible.

No se trata solo de saber qué es el DOM, sino de entender cómo interactuar con él de manera efectiva para construir experiencias de usuario ricas y dinámicas. En esta guía, no solo exploraremos los conceptos clave, sino que nos sumergiremos en una recopilación de ejercicios prácticos DOM JavaScript que te permitirán ver la teoría en acción y consolidar tus conocimientos. Desde añadir y eliminar elementos hasta clonar nodos y gestionar entradas de usuario, cubriremos escenarios comunes que te prepararán para desafíos del mundo real.

Prepárate para llevar tus habilidades de JavaScript al siguiente nivel y transformar tus sitios web de estáticos a interactivos y totalmente responsivos.

¿Qué es el DOM y por qué es crucial en el desarrollo web?

El Document Object Model (DOM) es una interfaz de programación para documentos HTML, XML y SVG. Proporciona una representación estructurada del documento (un árbol de nodos) y define cómo se puede acceder a esa estructura y manipularla programáticamente. En esencia, el DOM es el puente que permite a lenguajes de scripting como JavaScript interactuar con el contenido, la estructura y el estilo de una página web.

Imagina un documento HTML como un plano de construcción. El DOM es la representación interactiva de ese plano, donde cada elemento (un párrafo, una imagen, un botón) es un «objeto» con el que JavaScript puede «hablar». Sin el DOM, JavaScript no tendría forma de ver o modificar la página que el usuario ve.

La estructura del DOM: Nodos, elementos y atributos

El DOM organiza un documento en una estructura de árbol jerárquica, donde cada parte del documento es un «nodo». Los nodos pueden ser de diferentes tipos:

  • Nodos de Elemento: Representan etiquetas HTML como <div>, <p>, <a>, etc. Son los más comunes y con los que más interactuarás.
  • Nodos de Atributo: Representan los atributos de los elementos HTML, como id, class, src, href.
  • Nodos de Texto: Contienen el texto dentro de los elementos HTML.
  • Nodos de Comentario: Representan comentarios HTML.

Esta estructura de árbol facilita la navegación y la manipulación. Puedes moverte de un nodo padre a sus hijos, entre nodos hermanos, o de un hijo a su padre.

DOM vs. HTML: Entendiendo la diferencia

Aunque el DOM se construye a partir de un documento HTML, no son lo mismo. El HTML es el contenido inicial del documento que se carga en el navegador. El DOM es una representación en memoria de ese documento, que puede ser modificado por JavaScript. Esto significa que los cambios que realizas en el DOM a través de JavaScript no alteran el código HTML original de la página. Por ejemplo, si añades un nuevo párrafo con JavaScript, no verás ese párrafo en el archivo HTML fuente, pero sí en la inspección del DOM del navegador. Para profundizar en los conceptos fundamentales de JavaScript, te invito a explorar nuestros recursos.

La importancia de manipular el DOM eficientemente

La manipulación del DOM es una de las operaciones más costosas en términos de rendimiento web. Cada vez que modificas el DOM, el navegador tiene que recalcular el diseño (layout) y repintar (repaint) la página, lo que puede consumir recursos significativos. Por ello, la manipulación eficiente del DOM es crucial para crear aplicaciones web rápidas y fluidas. Prácticas como minimizar las manipulaciones directas, usar fragmentos de documento o la delegación de eventos son esenciales para optimizar el rendimiento. Según Google Developers, un DOM excesivamente grande puede ralentizar significativamente el rendimiento de una página.

Primeros pasos: Seleccionando y Accediendo a Elementos DOM

Antes de poder modificar cualquier cosa en el DOM, necesitas saber cómo encontrar los elementos que te interesan. JavaScript ofrece varias herramientas poderosas para seleccionar nodos específicos en tu documento.

document.querySelector() y document.querySelectorAll(): Tu arsenal de selección

Estas son las herramientas más versátiles y ampliamente utilizadas para seleccionar elementos en el DOM.

  • document.querySelector(): Devuelve el primer elemento del documento que coincide con el grupo especificado de selectores. Si no se encuentra ninguna coincidencia, devuelve null.
  • document.querySelectorAll(): Devuelve una NodeList estática que representa una lista de elementos del documento que coinciden con el grupo especificado de selectores.

Ambas funciones utilizan la sintaxis de selectores CSS, lo que las hace increíblemente flexibles. Puedes seleccionar por ID, clase, etiqueta, atributos y combinaciones de ellos. Para dominar los potentes selectores CSS y JavaScript, te recomendamos revisar nuestra guía detallada.

Acceso por ID, clase y etiqueta: Ejemplos prácticos

Además de querySelector, también existen métodos más específicos:

  • document.getElementById('miId'): Selecciona un elemento por su atributo id. Es muy eficiente ya que los IDs deben ser únicos.
  • document.getElementsByClassName('miClase'): Devuelve una colección HTML en vivo de todos los elementos con el nombre de clase dado.
  • document.getElementsByTagName('div'): Devuelve una colección HTML en vivo de todos los elementos con el nombre de etiqueta dado.

Veamos esto en acción con nuestros ejercicios.


Ejercicio 1: Añadir Elementos a una Lista Dinámicamente

En este primer ejercicio, aprenderemos a crear nuevos elementos HTML y a añadirlos a una lista existente en nuestra página. Esto es fundamental para construir interfaces interactivas donde el contenido se actualiza en tiempo real.

Imagina que tienes una lista de tareas y quieres que el usuario pueda añadir nuevas tareas con un simple clic.

El objetivo: Al hacer clic en un botón, se añade un nuevo ítem a una lista desordenada existente.

HTML:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Añadir Elementos DOM</title>
</head>
<body>
    <h1>Lista de tareas</h1>
    <ul id="miLista">
        <li>Tarea 1</li>
        <li>Tarea 2</li>
    </ul>
    <button id="agregar">Agregar elemento</button>

    <script src="script.js"></script>
</body>
</html>

JavaScript (script.js):

// Añadir un nuevo li a una lista al pulsar un botón
// Seleccionamos elementos
const lista = document.querySelector("#miLista");
const boton = document.querySelector("#agregar");

// Contador para enumerar los elementos nuevos
let contador = 3; 

// Creamos un nuevo elemento y lo agregamos al hacer clic
boton.addEventListener("click", () => {
    const nuevoElemento = document.createElement("li");
    nuevoElemento.textContent = `Tarea ${contador}`;
    contador++;
    lista.appendChild(nuevoElemento);
});

Explicación del código:

  1. Selección de Elementos: Utilizamos document.querySelector() para obtener referencias a la lista <ul> con id="miLista" y al botón con id="agregar".
  2. Contador: Una variable contador nos ayuda a numerar las nuevas tareas.
  3. Manejo de Eventos: boton.addEventListener("click", ...) escucha el evento de «click» en el botón. Cuando el usuario hace clic, se ejecuta la función de callback.
  4. Creación de un Nuevo Elemento: document.createElement("li") crea un nuevo nodo de elemento <li> en la memoria, pero aún no está en el DOM visible.
  5. Establecer Contenido: nuevoElemento.textContent = \Tarea ${contador}`;` asigna el texto al nuevo elemento.
  6. Añadir al DOM: lista.appendChild(nuevoElemento) es el paso clave. Inserta el nuevoElemento como el último hijo dentro del elemento lista (nuestra <ul>). Esto hace que el nuevo ítem sea visible en la página.
  7. Incrementar Contador: contador++; prepara el siguiente número de tarea.

Este ejercicio es una excelente base para entender cómo JavaScript interactúa con la estructura de tu HTML, permitiéndote añadir contenido dinámicamente.


Ejercicio 2: Eliminar el Último Elemento de una Lista

Así como podemos añadir elementos, también es crucial saber cómo eliminarlos. Este ejercicio se centra en quitar el último elemento de una lista, una funcionalidad común en aplicaciones de gestión de tareas o edición de contenido.

El objetivo: Eliminar el último ítem de una lista desordenada al hacer clic en un botón. Si no hay elementos, se muestra una alerta.

HTML:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Eliminar Elementos DOM</title>
</head>
<body>
    <h1>Lista de tareas</h1>
    <ul id="miLista">
        <li>Tarea 1</li>
        <li>Tarea 2</li>
        <li>Tarea 3</li>
    </ul>
    <button id="eliminar">Eliminar último elemento</button>

    <script src="script.js"></script>
</body>
</html>

JavaScript (script.js):

// Eliminar un elemento específico al pulsar otro botón
// Seleccionamos elementos
const lista = document.querySelector("#miLista");
const botonEliminar = document.querySelector("#eliminar");

// Eliminamos el último elemento
botonEliminar.addEventListener("click", () => {
    if (lista.lastElementChild) { // Verificar si hay elementos en la lista
        lista.lastElementChild.remove(); // O lista.removeChild(lista.lastElementChild);
    } else {
        alert("No hay más elementos para eliminar");
    }
});

Explicación del código:

  1. Selección de Elementos: Obtenemos la referencia a la lista y al botón de eliminar.
  2. Manejo de Eventos: Configuramos el eventListener para el botón de eliminar.
  3. Verificación de Elementos: if (lista.lastElementChild) es una comprobación vital. La propiedad lastElementChild devuelve el último elemento hijo de un nodo (o null si no tiene hijos). Esto previene errores al intentar eliminar algo que no existe.
  4. Eliminación del Elemento:
    • lista.lastElementChild.remove();: Este es el método más moderno y conciso para eliminar un elemento directamente.
    • Alternativamente, puedes usar lista.removeChild(lista.lastElementChild);. removeChild() requiere que se llame al método en el nodo padre (lista) y se le pase como argumento el nodo hijo que se desea eliminar (lista.lastElementChild).
  5. Alerta: Si no hay elementos en la lista, se muestra un mensaje al usuario.

Dominar la eliminación de elementos es tan importante como su adición para construir aplicaciones robustas y amigables.


Ejercicio 3: Clonar Elementos Existentes en el DOM

A veces, no necesitamos crear un elemento completamente nuevo, sino duplicar uno que ya existe en nuestra página. Esto es útil para plantillas de contenido repetitivo, como tarjetas de productos, elementos de noticias o, en nuestro caso, títulos.

El objetivo: Clonar un título existente y añadirlo al final del <body> de la página al hacer clic en un botón.

HTML:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Clonar Elementos DOM</title>
</head>
<body>
    <h2 id="titulo">Soy un título para clonar</h2>
    <button id="clonar">Clonar elemento</button>

    <script src="script.js"></script>
</body>
</html>

JavaScript (script.js):

// Clonar un elemento existente y añadirlo al final de la página
// Seleccionamos elementos
const elementoOriginal = document.querySelector("#titulo");
const botonClonar = document.querySelector("#clonar");

// Clonamos el elemento con todo su contenido y lo añadimos al final
botonClonar.addEventListener("click", () => {
    const elementoClonado = elementoOriginal.cloneNode(true); // 'true' para clonar hijos también
    document.body.appendChild(elementoClonado);
});

Explicación del código:

  1. Selección de Elementos: Obtenemos referencias al título original (h2 con id="titulo") y al botón.
  2. Manejo de Eventos: Configuramos el eventListener para el botón.
  3. Clonación:elementoOriginal.cloneNode(true) es la clave aquí.
    • cloneNode() crea una copia del nodo en el que se llama.
    • El parámetro true (o cualquier valor verdadero) indica que el clon debe ser «profundo», es decir, que también se clonen todos sus descendientes (hijos, nietos, etc.). Si se pasa false (o se omite), solo se clona el nodo en sí, sin sus hijos. Para elementos como un h2 que contienen texto, true es esencial para que el texto sea parte del clon.
  4. Añadir al Cuerpo: document.body.appendChild(elementoClonado) añade el elemento clonado como último hijo del <body>.

La clonación de nodos es una técnica muy útil para crear copias idénticas de secciones de HTML, lo que puede mejorar la eficiencia y la reusabilidad del código.


Ejercicio 4: Crear Bloques de Texto desde un Input

Este ejercicio combina la obtención de datos de un formulario con la creación dinámica de elementos. Es un patrón común en aplicaciones donde los usuarios introducen información que luego se muestra en la página, como en un chat, un muro de publicaciones o una lista de comentarios.

El objetivo: Crear un nuevo párrafo (<p>) con el texto introducido en un campo de input y añadirlo a un contenedor específico. Se incluye una validación básica para evitar bloques vacíos.

HTML:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Crear Bloques desde Input</title>
    <style>
        body { font-family: sans-serif; }
        #contenedor { border: 1px solid #ccc; padding: 15px; margin-top: 20px; min-height: 50px; }
    </style>
</head>
<body>
    <label for="texto">Escribe algo:</label>
    <input type="text" id="texto" placeholder="Tu texto aquí">
    <button id="crear">Crear bloque</button>

    <div id="contenedor"></div>

    <script src="script.js"></script>
</body>
</html>

JavaScript (script.js):

// Crear un bloque de texto con el valor de un input
// Seleccionamos elementos
const input = document.querySelector("#texto");
const boton = document.querySelector("#crear");
const contenedor = document.querySelector("#contenedor");

// Obtenemos el valor del input y creamos un nuevo bloque
boton.addEventListener("click", () => {
    const valor = input.value;

    if (valor.trim() === "") { // Validación para evitar texto vacío
        alert("Por favor, escribe algo antes de crear el bloque");
        return; // Detiene la ejecución si el input está vacío
    }

    // Creamos un nuevo bloque de texto (párrafo)
    const nuevoBloque = document.createElement("p");
    nuevoBloque.textContent = valor;

    // Añadimos el nuevo bloque al contenedor
    contenedor.appendChild(nuevoBloque);

    // Limpiamos el input después de añadir el texto
    input.value = ""; 
});

Explicación del código:

  1. Selección de Elementos: Obtenemos referencias al campo de texto (input con id="texto"), al botón de «Crear bloque» y al div donde se añadirán los párrafos (id="contenedor").
  2. Manejo de Eventos: El botón crear escucha los clics.
  3. Obtención del Valor del Input: const valor = input.value; recupera el texto actual del campo de entrada.
  4. Validación Básica: if (valor.trim() === "") comprueba si el valor del input, después de eliminar espacios en blanco al principio y al final con .trim(), está vacío. Si lo está, se muestra una alerta y la función return; detiene la ejecución para evitar crear un párrafo vacío.
  5. Creación y Contenido del Párrafo: Se crea un nuevo elemento <p> y su textContent se establece al valor obtenido del input.
  6. Añadir al Contenedor: contenedor.appendChild(nuevoBloque) inserta el nuevo párrafo dentro del div con id="contenedor".
  7. Limpiar Input: input.value = ""; vacía el campo de texto después de que el bloque ha sido creado, dejando el input listo para la siguiente entrada.

Este ejercicio demuestra cómo JavaScript puede procesar la entrada del usuario y reflejarla dinámicamente en la interfaz, un pilar fundamental de la interactividad web.


Buenas Prácticas y Consejos para la Manipulación del DOM

La manipulación del DOM es poderosa, pero si no se hace correctamente, puede llevar a problemas de rendimiento y a un código difícil de mantener. Aquí te dejamos algunos consejos para optimizar tus aplicaciones:

Optimización del rendimiento DOM

  • Minimiza las manipulaciones directas: Cada vez que modificas el DOM, el navegador tiene que recalcular y repintar la página. Agrupa varias modificaciones en una sola operación siempre que sea posible. Por ejemplo, si vas a añadir múltiples elementos a una lista, agrégalos a un fragmento de documento (ver siguiente punto) y luego añade el fragmento al DOM una sola vez.
  • Utiliza requestAnimationFrame para animaciones: Para animaciones o cambios visuales que ocurren en cada fotograma, usa requestAnimationFrame en lugar de setTimeout o setInterval. Esto permite al navegador optimizar las animaciones para que sean más suaves y eficientes.
  • Evita el «layout thrashing»: Esto ocurre cuando lees y escribes en el DOM repetidamente en un bucle, forzando al navegador a realizar cálculos de layout innecesarios. Agrupa todas las lecturas y luego todas las escrituras.
  • Considera frameworks y librerías: Librerías como React, Vue o Angular están diseñadas para optimizar la manipulación del DOM utilizando «DOM virtual», lo que mejora drásticamente el rendimiento al minimizar las operaciones directas.
  • Para más ideas y ejemplos, puedes explorar snippets JavaScript útiles para optimizar el rendimiento.

Evitar la manipulación directa excesiva: Fragmentos de documento

Cuando necesitas añadir muchos elementos al DOM de una vez, crear y adjuntar cada elemento individualmente puede ser ineficiente. Un DocumentFragment es un nodo DOM ligero que actúa como un contenedor temporal para otros nodos. Puedes construir tu estructura de DOM dentro del DocumentFragment y luego, cuando esté completa, añadir el fragmento al DOM real en una sola operación.

const fragmento = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
    const li = document.createElement('li');
    li.textContent = `Elemento ${i}`;
    fragmento.appendChild(li);
}
document.getElementById('miListaGrande').appendChild(fragmento);

Este enfoque reduce significativamente el número de repintados del navegador.

Delegación de eventos para mayor eficiencia

En lugar de adjuntar un eventListener a cada elemento individual en una lista grande (lo cual sería ineficiente), puedes adjuntar un único eventListener al elemento padre. Cuando un evento se dispara en un elemento hijo, burbujea hasta el padre. El manejador de eventos del padre puede entonces identificar qué elemento hijo originó el evento y reaccionar en consecuencia.

document.getElementById('miLista').addEventListener('click', function(event) {
    if (event.target.tagName === 'LI') {
        alert('Hiciste clic en: ' + event.target.textContent);
    }
});

La delegación de eventos reduce la cantidad de memoria utilizada y mejora el rendimiento, especialmente en listas dinámicas donde los elementos se añaden o eliminan con frecuencia. Puedes leer más sobre la delegación de eventos en la documentación de MDN Web Docs sobre burbujeo de eventos.


Recursos Adicionales para Profundizar en el DOM JavaScript

Para continuar tu viaje en el dominio del DOM, te recomiendo encarecidamente explorar las siguientes fuentes:

Documentación oficial y guías recomendadas

  • MDN Web Docs – Introducción al DOM: La referencia definitiva para cualquier concepto web. Ofrece explicaciones detalladas y ejemplos claros.
  • W3C – Document Object Model (DOM) Technical Reports: Para una comprensión profunda de los estándares que rigen el DOM. Es más técnico, pero fundamental para entender las bases.
  • JavaScript.info – Document Object Model: Una guía muy completa y amigable para principiantes y desarrolladores experimentados.

Comunidades y foros para resolver dudas

  • Stack Overflow: Si tienes dudas específicas o te encuentras con un problema, es muy probable que alguien más ya lo haya tenido y la solución esté en Stack Overflow.
  • Comunidades de desarrolladores en Discord o Slack: Participar en comunidades activas te permitirá hacer preguntas, compartir conocimientos y estar al tanto de las últimas tendencias.

Conclusión: Tu camino hacia el dominio del DOM

Hemos recorrido un camino esencial en el desarrollo web moderno: la manipulación del Document Object Model con JavaScript. Desde los conceptos fundamentales de cómo el DOM representa tu HTML hasta la ejecución de ejercicios prácticos DOM JavaScript para añadir, eliminar, clonar y crear elementos dinámicamente, has adquirido las herramientas clave para construir interfaces de usuario interactivas y dinámicas.

Recuerda que la práctica constante es la clave. Cada línea de código que escribas y cada error que depures te acercarán un paso más a la maestría. Experimenta con estos ejercicios, modifícalos, e intenta aplicarlos a tus propios proyectos. El DOM es el lienzo, y JavaScript, tu pincel. ¡Es hora de crear!

Hemos llegado al final de nuestra exploración del Document Object Model y su manipulación con JavaScript. Con estos ejercicios básicos hemos conocido los conceptos fundamentales de su estructura de árbol hasta la ejecución de ejercicios prácticos, además he subido un vídeo a YouTube donde puedes ver el procedimiento de los ejercicios y una muestra real de ellos. Esta es la parte 3 de 6 el resto en el enlace puedes ver el resto de ejercicios.


Preguntas Frecuentes (FAQ)

¿Qué es el DOM en JavaScript?

El DOM (Document Object Model) es una interfaz de programación para documentos HTML, XML y SVG. Permite que programas (como JavaScript) accedan y manipulen el contenido, la estructura y el estilo de los documentos. Es una representación en árbol de la página web.

¿Cuál es la diferencia entre innerHTML y textContent?

textContent obtiene o establece el contenido de texto de un nodo y sus descendientes, sin incluir el marcado HTML. innerHTML obtiene o establece el contenido HTML de un elemento, incluyendo las etiquetas. Usar textContent es más seguro para insertar texto ya que previene ataques de inyección de HTML (XSS).

¿Por qué la manipulación del DOM puede afectar el rendimiento?

Cada vez que se modifica el DOM, el navegador tiene que recalcular el diseño (reflow) y repintar (repaint) la página, lo que puede ser costoso en términos de rendimiento. Un exceso de manipulaciones o manipulaciones inefficientes pueden llevar a una interfaz de usuario lenta o «laggy».

¿Qué es la delegación de eventos y por qué es útil?

La delegación de eventos es una técnica en la que se adjunta un único eventListener a un elemento padre en lugar de a cada uno de sus hijos. Cuando un evento (como un clic) ocurre en un elemento hijo, burbujea hasta el padre, y el manejador del padre puede identificar qué hijo fue el objetivo original del evento. Esto es útil para optimizar el rendimiento y la memoria, especialmente en listas largas o dinámicas.

¿Cómo puedo evitar el «layout thrashing» al manipular el DOM?

El «layout thrashing» ocurre cuando se alternan repetidamente lecturas y escrituras del DOM en un bucle, forzando al navegador a realizar múltiples cálculos de layout. Para evitarlo, agrupa todas las lecturas del DOM primero, almacena los valores necesarios, y luego realiza todas las escrituras del DOM.

Scroll al inicio