L67 - Seleccionar y Manipular el DOM
🧠 Concepto
Section titled “🧠 Concepto”Para trabajar con el DOM necesitamos dos pasos: seleccionar elementos y luego manipularlos (cambiar su contenido, atributos, clases o estilos).
💻 Seleccionar elementos
Section titled “💻 Seleccionar elementos”querySelector() y querySelectorAll()
Section titled “querySelector() y querySelectorAll()”Los métodos más modernos y flexibles. Aceptan cualquier selector CSS.
// Selecciona el PRIMER elemento que coincidaconst header = document.querySelector('header');const boton = document.querySelector('.btn-primary');const primerItem = document.querySelector('#lista li:first-child');
// Selecciona TODOS los elementos que coincidan (NodeList estática)const items = document.querySelectorAll('.item');const celdas = document.querySelectorAll('table td');
// Se puede iterar directamente con forEachitems.forEach(item => { console.log(item.textContent);});getElementById()
Section titled “getElementById()”El más rápido para seleccionar por ID:
const logo = document.getElementById('logo');// Equivale a: document.querySelector('#logo')⚠️
querySelectorAlldevuelve una NodeList (estática).getElementsByClassNameogetElementsByTagNamedevuelven HTMLCollection (viva, se actualiza automáticamente si el DOM cambia).
// HTMLCollection viva vs NodeList estáticaconst divsVivos = document.getElementsByTagName('div'); // se actualiza soloconst divsEstaticos = document.querySelectorAll('div'); // no cambia📝 innerHTML vs textContent
Section titled “📝 innerHTML vs textContent”innerHTML
Section titled “innerHTML”Interpreta el contenido como HTML (peligroso si incluye datos del usuario):
const div = document.querySelector('#contenido');
// Interpreta etiquetas HTMLdiv.innerHTML = '<strong>Texto en negrita</strong>';// Resultado: Texto en negrita (en negrita visualmente)
// ⚠️ Peligro: XSS si el contenido viene del usuarioconst usuario = '<script>alert("hackeado")</script>';div.innerHTML = usuario; // ¡Ejecuta el script!textContent
Section titled “textContent”Trata todo como texto plano (seguro):
div.textContent = '<strong>Texto en negrita</strong>';// Resultado: <strong>Texto en negrita</strong> (se ve literal)
// Seguro con input del usuarioconst comentario = '<script>alert("xss")</script>';div.textContent = comentario; // Se muestra como texto, no se ejecuta| innerHTML | textContent | |
|---|---|---|
| Interpreta HTML | ✅ Sí | ❌ No |
| Seguridad | ⚠️ Riesgo XSS | ✅ Seguro |
| Rendimiento | Más lento (parsea HTML) | Más rápido |
| Caso de uso | Cuando necesitas HTML | Cuando solo quieres texto |
💻 setAttribute() y atributos
Section titled “💻 setAttribute() y atributos”const link = document.querySelector('a');
// Establecer atributoslink.setAttribute('href', 'https://ejemplo.com');link.setAttribute('target', '_blank');
// Leer atributosconsole.log(link.getAttribute('href'));
// Verificar si existeconsole.log(link.hasAttribute('target')); // true
// Eliminarlink.removeAttribute('target');
// Atributos data-* (dataset)link.dataset.id = '123';link.dataset.tipo = 'externo';console.log(link.dataset); // { id: '123', tipo: 'externo' }Atributos vs propiedades
Section titled “Atributos vs propiedades”Algunos atributos tienen su propiedad correspondiente en el objeto DOM:
const input = document.querySelector('input');
// Atributo (HTML)input.setAttribute('value', 'texto inicial');
// Propiedad (JavaScript, valor actual)input.value = 'texto modificado';
// ⚠️ No siempre se sincronizanconsole.log(input.getAttribute('value')); // 'texto inicial'console.log(input.value); // 'texto modificado'📝 classList
Section titled “📝 classList”La forma moderna de manejar clases CSS:
const elemento = document.querySelector('.mi-elemento');
// Añadir claseelemento.classList.add('activo');
// Quitar claseelemento.classList.remove('inactivo');
// Alternar (toggle)elemento.classList.toggle('visible');
// Reemplazarelemento.classList.replace('old-class', 'new-class');
// Verificar si tiene una claseconsole.log(elemento.classList.contains('activo')); // true
// Múltiples clases a la vezelemento.classList.add('clase1', 'clase2', 'clase3');className (alternativa antigua)
Section titled “className (alternativa antigua)”// ⚠️ className sobrescribe TODAS las claseselemento.className = 'nueva-clase';
// Para añadir sin perder las existenteselemento.className += ' otra-clase';💻 style.propiedad
Section titled “💻 style.propiedad”Manipular estilos en línea (equivalente al atributo style en HTML):
const caja = document.querySelector('.caja');
// Propiedades individuales (camelCase en JS)caja.style.backgroundColor = 'blue';caja.style.fontSize = '18px';caja.style.border = '2px solid red';
// Propiedades con prefijocaja.style.webkitTransform = 'rotate(45deg)'; // -webkit-transform
// Leer estilos computados (no los de style)const estilos = getComputedStyle(caja);console.log(estilos.backgroundColor); // rgb(0, 0, 255)console.log(estilos.fontSize); // 18pxcssText para múltiples estilos
Section titled “cssText para múltiples estilos”// Varias propiedades de una vezcaja.style.cssText = 'background: red; color: white; padding: 20px;';
// ⚠️ Esto SOBRESCRIBE todos los estilos en línea previos🎯 Ejemplo completo
Section titled “🎯 Ejemplo completo”// Seleccionarconst tarjeta = document.querySelector('.tarjeta');const titulo = tarjeta.querySelector('.titulo');const descripcion = tarjeta.querySelector('.descripcion');
// Manipular contenidotitulo.textContent = 'Nuevo título';descripcion.innerHTML = 'Contenido con <strong>negrita</strong>';
// Clasestarjeta.classList.add('destacado', 'animado');tarjeta.classList.remove('antiguo');
// Atributostarjeta.setAttribute('data-id', '42');tarjeta.dataset.status = 'activo';
// Estilostarjeta.style.borderRadius = '8px';tarjeta.style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)';🎯 Regla de oro: usa
querySelector/querySelectorAllpara seleccionar (son los más versátiles),textContentpara texto plano (más seguro),classListpara clases ystyle.propiedadpara estilos en línea puntuales.