|
|
|
# Módulo 3 — Interacción con el DOM y el BOM
|
|
|
|
# Módulo 3 — Interacción con el DOM y el BOM en TypeScript
|
|
|
|
|
|
|
|
## 1. Qué es el DOM
|
|
|
|
|
|
|
|
El **DOM (Document Object Model)** es una **representación estructurada del documento HTML** que permite acceder y modificar su contenido desde JavaScript. El resumen rápido es que es la representación en objetos de todas las etiquetas de un archivo html, accesibles por la etiqueta, por la id o por la clase.
|
|
|
|
El **DOM (Document Object Model)** es la representación estructurada del documento HTML en forma de **objetos tipados**, accesibles y manipulables desde TypeScript.
|
|
|
|
|
|
|
|
Cada etiqueta HTML se convierte en un **nodo** (el objeto) dentro de un árbol jerárquico.
|
|
|
|
Gracias al DOM, podemos **cambiar texto, estilos, atributos, crear o eliminar elementos**, y responder a la interacción del usuario. Al tratar cada elemento como un objeto, estos tienen atributos y métodos que son accesibles desde el navegador mediante *javascritp*.
|
|
|
|
En TypeScript, el DOM cobra especial importancia porque:
|
|
|
|
|
|
|
|
* Los elementos HTML están **fuertemente tipados** (`HTMLElement`, `HTMLButtonElement`, etc.)
|
|
|
|
* Se detectan errores comunes en tiempo de desarrollo
|
|
|
|
* Se fuerza a comprobar la existencia real de los nodos
|
|
|
|
|
|
|
|
Cada etiqueta HTML se convierte en un **nodo** dentro de un árbol jerárquico.
|
|
|
|
|
|
|
|
```html
|
|
|
|
<!-- index.html -->
|
| ... | ... | @@ -14,51 +19,48 @@ Gracias al DOM, podemos **cambiar texto, estilos, atributos, crear o eliminar el |
|
|
|
<p id="mensaje"></p>
|
|
|
|
```
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
// app.js - Selección de elemento por id
|
|
|
|
const titulo = document.getElementById("titulo");
|
|
|
|
const boton = document.getElementById("btnActualizar");
|
|
|
|
const mensaje = document.getElementById("mensaje");
|
|
|
|
```ts
|
|
|
|
// app.ts
|
|
|
|
const titulo = document.getElementById('titulo') as HTMLHeadingElement;
|
|
|
|
const boton = document.getElementById('btnActualizar') as HTMLButtonElement;
|
|
|
|
const mensaje = document.getElementById('mensaje') as HTMLParagraphElement;
|
|
|
|
|
|
|
|
boton.addEventListener("click", () => {
|
|
|
|
mensaje.textContent = "Recursos actualizados correctamente";
|
|
|
|
titulo.style.color = "green";
|
|
|
|
boton.addEventListener('click', (): void => {
|
|
|
|
mensaje.textContent = 'Recursos actualizados correctamente';
|
|
|
|
titulo.style.color = 'green';
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
El DOM nos permite **modificar la interfaz del usuario sin recargar la página**.
|
|
|
|
> En TypeScript, es habitual usar **type assertions** (`as HTML...`) o comprobaciones de null.
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 2. Qué es el BOM
|
|
|
|
|
|
|
|
El **BOM (Browser Object Model)** es el modelo de objetos del **navegador**, que nos da acceso a elementos externos al documento HTML:
|
|
|
|
la **ventana (`window`)**, la **barra de direcciones (`location`)**, el **historial (`history`)**, o el **temporizador (`setTimeout`, `setInterval`)**. Estos elementos también se tratan como objetos, dando la posibilidad de manejarlos desde el código de *javascript*.
|
|
|
|
El **BOM (Browser Object Model)** representa los objetos propios del navegador, accesibles mediante `window`.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
console.log(window.innerWidth); // ancho de la ventana
|
|
|
|
console.log(location.href); // URL actual
|
|
|
|
TypeScript proporciona tipado completo para estos objetos.
|
|
|
|
|
|
|
|
// Redireccionar
|
|
|
|
// location.href = "https://hospitalcentral.com";
|
|
|
|
```ts
|
|
|
|
console.log(window.innerWidth);
|
|
|
|
console.log(window.location.href);
|
|
|
|
|
|
|
|
// Temporizadores
|
|
|
|
setTimeout(() => alert("Datos cargados correctamente"), 2000);
|
|
|
|
setTimeout((): void => {
|
|
|
|
alert('Datos cargados correctamente');
|
|
|
|
}, 2000);
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 3. Acceso a elementos del DOM
|
|
|
|
|
|
|
|
Podemos obtener referencias a los elementos HTML usando distintos métodos:
|
|
|
|
TypeScript mantiene los mismos métodos de acceso, pero con **tipos concretos**.
|
|
|
|
|
|
|
|
| Método | Descripción | Ejemplo |
|
|
|
|
| -------------------------- | ------------------------------------------------------------ | -------------------------------------------- |
|
|
|
|
| `getElementById()` | Selecciona un elemento por su `id` | `document.getElementById("titulo")` |
|
|
|
|
| `getElementsByClassName()` | Devuelve una colección de elementos con esa clase | `document.getElementsByClassName("recurso")` |
|
|
|
|
| `getElementsByTagName()` | Devuelve una colección de etiquetas | `document.getElementsByTagName("p")` |
|
|
|
|
| `querySelector()` | Devuelve el primer elemento que coincide con un selector CSS | `document.querySelector(".boton")` |
|
|
|
|
| `querySelectorAll()` | Devuelve **todos** los elementos que coinciden | `document.querySelectorAll(".boton")` |
|
|
|
|
| Método | Tipo devuelto | Observaciones | |
|
|
|
|
| ------------------ | --------------------- | ------------- | ---------------- |
|
|
|
|
| `getElementById` | `HTMLElement | null` | Debe comprobarse |
|
|
|
|
| `querySelector` | `Element | null` | Se puede tipar |
|
|
|
|
| `querySelectorAll` | `NodeListOf<Element>` | Iterable | |
|
|
|
|
|
|
|
|
```html
|
|
|
|
<ul>
|
| ... | ... | @@ -67,73 +69,62 @@ Podemos obtener referencias a los elementos HTML usando distintos métodos: |
|
|
|
</ul>
|
|
|
|
```
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
const recursos = document.querySelectorAll(".recurso");
|
|
|
|
recursos.forEach(r => console.log(r.textContent));
|
|
|
|
```ts
|
|
|
|
const recursos = document.querySelectorAll<HTMLLIElement>('.recurso');
|
|
|
|
recursos.forEach((r: HTMLLIElement) => {
|
|
|
|
console.log(r.textContent);
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 4. Manipulación del DOM
|
|
|
|
|
|
|
|
Podemos **crear, modificar o eliminar elementos** dinámicamente.
|
|
|
|
|
|
|
|
### Crear elementos
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
const lista = document.querySelector("#listaRecursos");
|
|
|
|
const nuevo = document.createElement("li");
|
|
|
|
nuevo.textContent = "Medicos";
|
|
|
|
```ts
|
|
|
|
const lista = document.getElementById('listaRecursos') as HTMLUListElement;
|
|
|
|
const nuevo = document.createElement('li');
|
|
|
|
nuevo.textContent = 'Médicos';
|
|
|
|
lista.appendChild(nuevo);
|
|
|
|
```
|
|
|
|
|
|
|
|
### Modificar contenido
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
document.querySelector("#titulo").textContent = "Recursos actualizados";
|
|
|
|
```ts
|
|
|
|
const titulo = document.querySelector('#titulo') as HTMLHeadingElement;
|
|
|
|
titulo.textContent = 'Recursos actualizados';
|
|
|
|
```
|
|
|
|
|
|
|
|
### Cambiar estilos y atributos
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
const mensaje = document.getElementById("mensaje");
|
|
|
|
mensaje.style.color = "blue";
|
|
|
|
mensaje.setAttribute("class", "alerta");
|
|
|
|
```ts
|
|
|
|
const mensaje = document.getElementById('mensaje') as HTMLParagraphElement;
|
|
|
|
mensaje.style.color = 'blue';
|
|
|
|
mensaje.classList.add('alerta');
|
|
|
|
```
|
|
|
|
|
|
|
|
### Eliminar elementos
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
lista.removeChild(lista.lastElementChild);
|
|
|
|
```ts
|
|
|
|
if (lista.lastElementChild) {
|
|
|
|
lista.removeChild(lista.lastElementChild);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 5. Eventos en JavaScript
|
|
|
|
|
|
|
|
Los **eventos** son acciones que suceden en la página: clics, desplazamientos, escritura, carga, etc.
|
|
|
|
Podemos **escucharlos y responder** mediante tres formas:
|
|
|
|
|
|
|
|
### 5.1. En el HTML directamente
|
|
|
|
|
|
|
|
```html
|
|
|
|
<button onclick="alert('Recurso añadido')">Añadir recurso</button>
|
|
|
|
```
|
|
|
|
## 5. Eventos en TypeScript
|
|
|
|
|
|
|
|
### 5.2. Asignando una propiedad en JS
|
|
|
|
En TypeScript, los eventos están **tipados**, lo que evita errores comunes.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
const boton = document.getElementById("btnGuardar");
|
|
|
|
boton.onclick = function() {
|
|
|
|
alert("Recurso guardado correctamente");
|
|
|
|
};
|
|
|
|
```
|
|
|
|
### Usando `addEventListener` (forma recomendada)
|
|
|
|
|
|
|
|
### 5.3. Usando `addEventListener()` (forma recomendada)
|
|
|
|
```ts
|
|
|
|
const boton = document.getElementById('btnGuardar') as HTMLButtonElement;
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
boton.addEventListener("click", () => {
|
|
|
|
console.log("Evento capturado con addEventListener");
|
|
|
|
boton.addEventListener('click', (event: MouseEvent): void => {
|
|
|
|
console.log('Recurso guardado correctamente');
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
| ... | ... | @@ -141,14 +132,22 @@ boton.addEventListener("click", () => { |
|
|
|
|
|
|
|
## 6. Tipos comunes de eventos
|
|
|
|
|
|
|
|
| Evento | Descripción | Ejemplo |
|
|
|
|
| ------------------------ | ---------------------------------- | --------------------------------------- |
|
|
|
|
| `click` | Clic del usuario | `button.addEventListener("click", fn)` |
|
|
|
|
| `input` | Cambio en un campo de texto | `input.addEventListener("input", fn)` |
|
|
|
|
| `change` | Valor modificado en select o input | `select.addEventListener("change", fn)` |
|
|
|
|
| `mouseover` / `mouseout` | Al pasar o salir el ratón | `div.addEventListener("mouseover", fn)` |
|
|
|
|
| `submit` | Envío de formulario | `form.addEventListener("submit", fn)` |
|
|
|
|
| `load` | Cuando la página termina de cargar | `window.addEventListener("load", fn)` |
|
|
|
|
| Evento | Tipo de evento |
|
|
|
|
| -------- | -------------- |
|
|
|
|
| `click` | `MouseEvent` |
|
|
|
|
| `input` | `InputEvent` |
|
|
|
|
| `change` | `Event` |
|
|
|
|
| `submit` | `SubmitEvent` |
|
|
|
|
| `load` | `Event` |
|
|
|
|
|
|
|
|
```ts
|
|
|
|
const input = document.getElementById('nuevoRecurso') as HTMLInputElement;
|
|
|
|
|
|
|
|
input.addEventListener('input', (e: Event): void => {
|
|
|
|
const valor = (e.target as HTMLInputElement).value;
|
|
|
|
console.log(valor);
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
| ... | ... | @@ -164,49 +163,47 @@ boton.addEventListener("click", () => { |
|
|
|
<button id="btnAgregar">Agregar</button>
|
|
|
|
```
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
const lista = document.getElementById("listaRecursos");
|
|
|
|
const input = document.getElementById("nuevoRecurso");
|
|
|
|
const boton = document.getElementById("btnAgregar");
|
|
|
|
```ts
|
|
|
|
const lista = document.getElementById('listaRecursos') as HTMLUListElement;
|
|
|
|
const input = document.getElementById('nuevoRecurso') as HTMLInputElement;
|
|
|
|
const boton = document.getElementById('btnAgregar') as HTMLButtonElement;
|
|
|
|
|
|
|
|
boton.addEventListener("click", () => {
|
|
|
|
boton.addEventListener('click', (): void => {
|
|
|
|
const valor = input.value.trim();
|
|
|
|
if (valor !== "") {
|
|
|
|
const li = document.createElement("li");
|
|
|
|
|
|
|
|
if (valor !== '') {
|
|
|
|
const li = document.createElement('li');
|
|
|
|
li.textContent = valor;
|
|
|
|
lista.appendChild(li);
|
|
|
|
input.value = "";
|
|
|
|
input.value = '';
|
|
|
|
} else {
|
|
|
|
alert("Por favor, ingresa un nombre de recurso");
|
|
|
|
alert('Por favor, ingresa un nombre de recurso');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
> Con este ejemplo, el sistema de gestión de recursos permite **agregar nuevos recursos desde la interfaz**, aplicando lo aprendido sobre **DOM y eventos**.
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 8. Interacción con el BOM: Ventanas y temporizadores
|
|
|
|
## 8. Interacción con el BOM: ventanas y temporizadores
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
// Confirmar acción
|
|
|
|
if (confirm("¿Deseas guardar los cambios?")) {
|
|
|
|
alert("Cambios guardados");
|
|
|
|
```ts
|
|
|
|
if (confirm('¿Deseas guardar los cambios?')) {
|
|
|
|
alert('Cambios guardados');
|
|
|
|
} else {
|
|
|
|
alert("Acción cancelada");
|
|
|
|
alert('Acción cancelada');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Temporizador repetido
|
|
|
|
setInterval(() => {
|
|
|
|
console.log("Sincronizando datos...");
|
|
|
|
setInterval((): void => {
|
|
|
|
console.log('Sincronizando datos...');
|
|
|
|
}, 5000);
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 9. Buenas prácticas
|
|
|
|
## 9. Buenas prácticas en TypeScript
|
|
|
|
|
|
|
|
* Comprobar siempre valores `null` al acceder al DOM.
|
|
|
|
* Evitar manipulaciones directas de estilo; preferir CSS.
|
|
|
|
* Usar tipos específicos (`HTMLInputElement`, `HTMLButtonElement`).
|
|
|
|
* Centralizar la lógica interactiva en funciones.
|
|
|
|
|
|
|
|
- Mantén **separado el HTML del JS** (usa eventos con `addEventListener`).
|
|
|
|
- Siempre que sea posible, usa el **css** para la edición de estilos y no el **js**, para no saturar el navegador.
|
|
|
|
- Usa `const` y `let` para referencias seguras.
|
|
|
|
- Usa funciones para reutilizar comportamientos interactivos. |