From 973e2834557d3d092e48e0cb888c22a78e648fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Ribal=20del=20R=C3=ADo?= Date: Mon, 2 Mar 2026 12:17:53 +0100 Subject: [PATCH 1/3] feat: intermedio --- pages/Bloque3/Intermedio.qmd | 643 +++++++++++++++++++++++++++++++++++ 1 file changed, 643 insertions(+) create mode 100644 pages/Bloque3/Intermedio.qmd diff --git a/pages/Bloque3/Intermedio.qmd b/pages/Bloque3/Intermedio.qmd new file mode 100644 index 0000000..1924ce3 --- /dev/null +++ b/pages/Bloque3/Intermedio.qmd @@ -0,0 +1,643 @@ +--- +title: "React III" +subtitle: "*Controlled fields*, `useEffect` " +author: "Javier Ribal del Río" +date: "2026-02-27" +date-modified: today +affiliation: "Hyperloop UPV" + +format: + html: default + revealjs: + history: false + chalkboard: true + output-file: intermedio.html + parallax-background-image: ../../img/fondo.png + parallax-background-size: "cover" + pdf: default +format-links: + - pdf + - format: revealjs + text: Presentación + icon: file-slides +--- + + +**Contenido** + +- *Controlled Inputs* +- Concepto de Hook +- *Hook* `useEffect` +- Introducción a API para la descarga de datos + + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## *Controlled Inputs* + +### Motivación + +Hasta ahora se ha trabajado con eventos capturando acciones del usuario. + +Sin embargo, al trabajar con formularios surge una cuestión fundamental: + +> ¿Quién controla el valor del input? +> ¿El DOM o React? + +::: {.content-visible when-format="revealjs"} + +--- + +::: + + +Recordemos que en HTML puro o, el valor de un `` está gestionado directamente por el DOM. + +En React, podemos hacer que el valor del input esté controlado por el estado del componente. + +A esto lo llamamos **controlled input**. + + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### ¿Qué es un controlled input? + +Un *controlled input* es un elemento de formulario cuyo valor: + +- Está almacenado en el estado del componente +- Se actualiza mediante un evento (`onChange`) +- Se renderiza utilizando ese mismo estado + +**Única fuente de verdad (*single source of truth*).** + + + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Estructura del componente controlled +```{.jsx code-line-numbers="|4|6,7,8|4,13|6,7,8,14|1,16"} +import { useState } from "react"; +function FormularioNombre() { + + const [nombre, setNombre] = useState(""); + + function manejarCambio(event) { + setNombre(event.target.value); + } + + return ( +
+ +

El nombre introducido es: {nombre}

+
+ ); +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +#### Análisis del ejemplo + +El valor del input se sincroniza con el estado + +1. Declaramos una variable de estado: nombre +2. Asociamos el atributo value del input a ese estado +3. Capturamos el evento onChange +4. Actualizamos el estado con setNombre + + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +Cada vez que el estado cambia: +El componente se vuelve a ejecutar +El JSX se vuelve a generar +El valor del input se sincroniza con el estado + + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Ejemplo Formulario + +```{.jsx} +import { useState } from "react"; + +function FormularioSimple() { + + const [email, setEmail] = useState(""); + + function handleChange(event) { + setEmail(event.target.value); + } + + function handleSubmit(event) { + event.preventDefault(); // Evita la recarga del navegador + + console.log("Formulario enviado"); + console.log("Email:", email); + + setEmail(""); // Limpieza opcional del campo + } + + return ( +
+ + +
+ ); +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + + +Referencia: [https://es.react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable](https://es.react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable) + + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## Hooks (Repaso) + +- Función especial que permite modificar las propiedades internas de los componentes +- Características avanzadas +- Modificación del `life-cycle` +- Normalmente forma `use____` + + +::: {.content-visible when-format="revealjs"} + +--- + +::: + + +## `useEffect` + +- `useEffect` es un Hook que permite ejecutar efectos secundarios dentro de un componente funcional. +- Un efecto secundario es cualquier operación que no sea simplemente devolver JSX (por ejemplo: peticiones a un servidor, temporizadores, suscripciones). +- Se ejecuta después de que el componente se renderiza en el DOM. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + + +### Métodos de uso de `useEffect` + + +#### 1. Sin array de dependencias + +``` jsx +useEffect(() => { + console.log("Se ejecuta en cada render"); +}); +``` + +**Comportamiento:** + +- Se ejecuta después de cada renderizado. +- No existe control sobre la frecuencia. +- Puede generar bucles si modifica estado sin control. + +**Interpretación conceptual:** + +El efecto acompaña siempre al render. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + + +#### 2. Con array vacío + +``` jsx +useEffect(() => { + console.log("Se ejecuta solo una vez"); +}, []); +``` + +**Comportamiento:** + +- Se ejecuta únicamente tras el primer render. +- Equivalente conceptual al "montaje" del componente. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +**Uso habitual:** + +- Peticiones a servidor +- Inicializaciones +- Suscripciones + +**Interpretación conceptual:** + +El efecto ocurre una única vez al crear el componente. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +#### 3. Con dependencias específicas + +``` jsx +useEffect(() => { + console.log("Se ejecuta cuando cambia contador"); +}, [contador]); +``` + +**Comportamiento:** + +- Se ejecuta tras el primer render. +- Se vuelve a ejecutar cuando cambia alguna variable del array. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +**Interpretación conceptual:** + +El efecto depende del estado indicado. + +React compara el valor anterior con el nuevo y decide si debe ejecutar +el efecto. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## `fetch()` + +Hasta ahora nuestros componentes eran completamente locales. + +Sin embargo, en aplicaciones reales necesitamos: + +- Descargar datos +- Conectarnos a servidores +- Trabajar con APIs externas + +Para ello utilizamos `fetch()`. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Ejemplo mínimo de `fetch` + +```jsx +fetch("https://pokeapi.co/api/v2/pokemon/1") + .then(response => response.json()) + .then(data => console.log(data)); +``` + +Utiliza las *Promises* + + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +Interpretación simple: + +1. Se hace una petición a una URL +2. Se transforma la respuesta a formato JSON +3. Se accede a los datos + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### `fetch()` dentro de `useEffect` + +En React, lo habitual es realizar la descarga cuando el componente se monta. + +Para ello: + +- Utilizamos `useEffect` +- Añadimos array vacío `[]` +- Guardamos los datos en el estado + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Ejemplo integrado + +```jsx +import { useState, useEffect } from "react"; + +function Pokemon() { + + const [pokemon, setPokemon] = useState(null); + + useEffect(() => { + + fetch("https://pokeapi.co/api/v2/pokemon/1") + .then(response => response.json()) + .then(data => setPokemon(data)); + + }, []); + + if (!pokemon) return

Cargando...

; + + return ( +
+

{pokemon.name}

+ {pokemon.name} +
+ ); +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Flujo conceptual + +1. Render inicial +2. Se ejecuta `useEffect` +3. Se lanza la petición +4. Se actualiza el estado +5. Nuevo render con los datos + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Advertencia importante + +Si eliminamos el array vacío: + +```jsx +useEffect(() => { + fetch("https://pokeapi.co/api/v2/pokemon/1") + .then(res => res.json()) + .then(data => setPokemon(data)); +}); +``` + +El efecto se ejecutará en cada render. + +Como actualizar estado provoca render, se generará un bucle infinito. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + + +`useEffect` conecta React con el exterior. +`fetch()` permite traer datos del exterior. +El estado vuelve a controlar el render. + +En la siguiente sección formalizaremos esto utilizando `async / await`. + + + +## `async` y `await` + +Hasta ahora hemos utilizado `fetch()` con encadenamiento. + +Existe una forma más clara y estructurada de escribir código asíncrono: + +- `async` +- `await` + +Su objetivo es hacer que el código sea más legible. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### ¿Qué significa `async`? + +- Se coloca delante de una función +- Indica que la función trabajará con operaciones asíncronas + +```jsx +async function ejemplo() { + console.log("Función asíncrona"); +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### ¿Qué significa `await`? + +- Solo puede utilizarse dentro de una función `async` +- Detiene la ejecución hasta que la operación finaliza +- Hace que el código se lea de forma secuencial + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Ejemplo básico con `fetch` + +```jsx +async function obtenerPokemon() { + + const response = await fetch( + "https://pokeapi.co/api/v2/pokemon/1" + ); + + const data = await response.json(); + + console.log(data); +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +Interpretación conceptual: + +1. Se realiza la petición +2. Se espera la respuesta +3. Se transforma a JSON +4. Se trabaja con los datos + +El código se lee de arriba hacia abajo. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### `async / await` dentro de `useEffect` + +En React, lo habitual es declarar una función interna y ejecutarla. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Ejemplo completo + +```jsx +import { useState, useEffect } from "react"; + +function Pokemon() { + + const [pokemon, setPokemon] = useState(null); + + useEffect(() => { + + async function fetchData() { + + const response = await fetch( + "https://pokeapi.co/api/v2/pokemon/1" + ); + + const data = await response.json(); + + setPokemon(data); + } + + fetchData(); + + }, []); + + if (!pokemon) return

Cargando...

; + + return ( +
+

{pokemon.name}

+ {pokemon.name} +
+ ); +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### ¿Por qué no hacer directamente? + +```jsx +useEffect(async () => { + ... +}, []); +``` + +Porque `useEffect` no debe recibir una función asíncrona directamente. + +Por eso declaramos la función dentro y luego la ejecutamos. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Flujo mental con `async / await` + +1. Render inicial +2. Se ejecuta `useEffect` +3. Se llama a la función asíncrona +4. `await` espera la respuesta +5. Se actualiza el estado +6. Nuevo render + +::: {.content-visible when-format="revealjs"} + +--- + +::: + + +`async / await` no cambia lo que hace el programa. + +Solo cambia la forma de escribirlo: + +Más claro. +Más estructurado. +Más fácil de mantener. \ No newline at end of file From c5ef5adcd9a123a99107014adf6a3efca94cf97d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Ribal=20del=20R=C3=ADo?= Date: Mon, 2 Mar 2026 12:19:45 +0100 Subject: [PATCH 2/3] chore: add ignored --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 023de01..2175ac7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ _book/ *_cache/ notas.csv + +ignored/ \ No newline at end of file From ebbbd936626398144de3726027704b0ee47b18fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Ribal=20del=20R=C3=ADo?= Date: Wed, 4 Mar 2026 09:33:36 +0100 Subject: [PATCH 3/3] feat: S09 --- _freeze/rubriuca/execute-results/tex.json | 4 +- _quarto.yml | 6 + docs/about.html | 8 +- docs/about.pdf | Bin 15453 -> 15453 bytes docs/index.html | 31 +- docs/index.pdf | Bin 39345 -> 39345 bytes docs/pages/Bloque1/MAcss.html | 33 +- docs/pages/Bloque1/MAcss.pdf | Bin 24989 -> 24989 bytes docs/pages/Bloque1/MAhtml2.html | 33 +- docs/pages/Bloque1/MAhtml2.pdf | Bin 24870 -> 24870 bytes docs/pages/Bloque1/bloque1.html | 33 +- docs/pages/Bloque1/bloque1.pdf | Bin 31777 -> 31777 bytes docs/pages/Bloque1/css.html | 33 +- docs/pages/Bloque1/css.pdf | Bin 74234 -> 74234 bytes docs/pages/Bloque1/css_p.html | 4 +- docs/pages/Bloque1/ehtml.html | 4 +- docs/pages/Bloque1/entorno-reveal.html | 4 +- docs/pages/Bloque1/entorno.html | 33 +- docs/pages/Bloque1/entorno.pdf | Bin 651767 -> 651767 bytes docs/pages/Bloque1/html.html | 33 +- docs/pages/Bloque1/html.pdf | Bin 738180 -> 738180 bytes docs/pages/Bloque1/t1.html | 33 +- docs/pages/Bloque1/t1.pdf | Bin 34403 -> 34403 bytes docs/pages/Bloque1/t1a.html | 33 +- docs/pages/Bloque1/t1a.pdf | Bin 21359 -> 21359 bytes docs/pages/Bloque1/t2.html | 33 +- docs/pages/Bloque1/t2.pdf | Bin 26811 -> 26811 bytes docs/pages/Bloque1/t2a.html | 33 +- docs/pages/Bloque1/t2a.pdf | Bin 22584 -> 22584 bytes docs/pages/Bloque2/MAclases.html | 33 +- docs/pages/Bloque2/MAclases.pdf | Bin 60262 -> 60262 bytes docs/pages/Bloque2/intensivo.html | 33 +- docs/pages/Bloque2/intensivo.pdf | Bin 77061 -> 77061 bytes docs/pages/Bloque2/jsI-reveal.html | 4 +- docs/pages/Bloque2/jsI.html | 10 +- docs/pages/Bloque2/jsI.pdf | Bin 45683 -> 45683 bytes docs/pages/Bloque2/ti.html | 33 +- docs/pages/Bloque2/ti.pdf | Bin 47554 -> 47554 bytes docs/pages/Bloque2/tia.html | 33 +- docs/pages/Bloque2/tia.pdf | Bin 55042 -> 55042 bytes docs/pages/Bloque3/DOM.html | 33 +- docs/pages/Bloque3/DOM.pdf | Bin 49517 -> 49517 bytes docs/pages/Bloque3/Intermedio.html | 1465 +++++++++++++++++ docs/pages/Bloque3/Intermedio.pdf | Bin 0 -> 83354 bytes docs/pages/Bloque3/MARef.html | 1005 +++++++++++ docs/pages/Bloque3/MARef.pdf | Bin 0 -> 33614 bytes docs/pages/Bloque3/MAcss2.html | 33 +- docs/pages/Bloque3/MAcss2.pdf | Bin 25926 -> 25926 bytes docs/pages/Bloque3/PokeAPI-Example.zip | Bin 0 -> 1267 bytes docs/pages/Bloque3/ReactI.html | 33 +- docs/pages/Bloque3/ReactI.pdf | Bin 73971 -> 73971 bytes docs/pages/Bloque3/dom.html | 4 +- docs/pages/Bloque3/intermedio.html | 1039 ++++++++++++ docs/pages/Bloque3/ps.html | 33 +- docs/pages/Bloque3/ps.pdf | Bin 38340 -> 38340 bytes docs/pages/Bloque3/reactI.html | 4 +- docs/pages/Bloque3/t6.html | 33 +- docs/pages/Bloque3/t6.pdf | Bin 67989 -> 67989 bytes docs/pages/rubric.html | 33 +- docs/rubriuca.pdf | Bin 33704 -> 38663 bytes docs/search.json | 1465 +++++++++-------- ...dark-4d9afe2b8d18ee9fa5d0d57b5ed4214d.css} | 2 +- ...ting-ed96de9b727972fe78a7b5d16c58bf87.css} | 2 +- pages/Bloque3/Intermedio.qmd | 9 +- pages/Bloque3/MARef.qmd | 21 + pages/Bloque3/PokeAPI-Example.zip | Bin 0 -> 1267 bytes rubriuca.qmd | 14 +- 67 files changed, 4982 insertions(+), 783 deletions(-) create mode 100644 docs/pages/Bloque3/Intermedio.html create mode 100644 docs/pages/Bloque3/Intermedio.pdf create mode 100644 docs/pages/Bloque3/MARef.html create mode 100644 docs/pages/Bloque3/MARef.pdf create mode 100644 docs/pages/Bloque3/PokeAPI-Example.zip create mode 100644 docs/pages/Bloque3/intermedio.html rename docs/site_libs/quarto-html/{quarto-syntax-highlighting-dark-b758ccaa5987ceb1b75504551e579abf.css => quarto-syntax-highlighting-dark-4d9afe2b8d18ee9fa5d0d57b5ed4214d.css} (98%) mode change 100755 => 100644 rename docs/site_libs/quarto-html/{quarto-syntax-highlighting-587c61ba64f3a5504c4d52d930310e48.css => quarto-syntax-highlighting-ed96de9b727972fe78a7b5d16c58bf87.css} (98%) mode change 100755 => 100644 create mode 100644 pages/Bloque3/MARef.qmd create mode 100644 pages/Bloque3/PokeAPI-Example.zip diff --git a/_freeze/rubriuca/execute-results/tex.json b/_freeze/rubriuca/execute-results/tex.json index 8df0a85..5005ca2 100644 --- a/_freeze/rubriuca/execute-results/tex.json +++ b/_freeze/rubriuca/execute-results/tex.json @@ -1,8 +1,8 @@ { - "hash": "4c531019abecc8cc6539dab4946a25d0", + "hash": "fc48ebabec45b3cfdc76aeaaf6efbe0a", "result": { "engine": "knitr", - "markdown": "---\ncache: false\nformat:\n pdf:\n pdf-engine: xelatex\n toc: false\n number-sections: false\nexecute:\n echo: false\n warning: false\n message: false\nheader-includes:\n - \\usepackage{array}\n - \\usepackage{colortbl}\n - \\usepackage{xcolor}\n - \\usepackage{longtable}\n - \\renewcommand{\\arraystretch}{1.4}\n---\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n# Rúbrica de Evaluación\n\n**Tarea:** Web de Hyperloop II \n**Alumno:** Pau Minguet Micó\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n\\begin{table}[!h]\n\\centering\\begingroup\\fontsize{7}{9}\\selectfont\n\n\\begin{tabular}{|>{\\centering\\arraybackslash}p{2cm}|>{\\centering\\arraybackslash}p{0.5cm}|>{\\centering\\arraybackslash}p{2.0cm}|>{\\centering\\arraybackslash}p{2.0cm}|>{\\centering\\arraybackslash}p{2.0cm}|>{\\centering\\arraybackslash}p{2.0cm}|>{\\centering\\arraybackslash}p{2.0cm}|>{\\centering\\arraybackslash}p{1.4cm}|}\n\\hline\n\\cellcolor{gray!35}{\\textbf{\\textbf{Criterio}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{N/A}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Deficiente}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Insuficiente}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Aceptable}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Bueno}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Excelente}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Puntuación}}}\\\\\n\\hline\n\\cellcolor{gray!25}{\\textbf{\\textbf{Diseño}}} & & \\footnotesize Diseño desordenado y/o con problemas de visualización funcional. & \\footnotesize Diseño básico pero con problemas de visualización o estructura. & \\footnotesize Diseño claro y ordenado, cumple los requisitos básicos. & \\cellcolor{gray!15}\\textbf{7.5}\\newline \\footnotesize Diseño cuidado, buena estética y estructura clara. & \\footnotesize Diseño profesional, limpio, pulido y sobresaliente. & \\textbf{7.5}\\\\\n\\hline\n\\cellcolor{gray!25}{\\textbf{\\textbf{Programación}}} & \\cellcolor{gray!15}\\textbf{N/A} & & & & & & —\\\\\n\\hline\n\\cellcolor{gray!25}{\\textbf{\\textbf{Esfuerzo e implicación}}} & & \\footnotesize Bajo esfuerzo o dedicación mínima. & \\footnotesize Esfuerzo adecuado pero limitado. & \\footnotesize Esfuerzo notable, cumple con lo requerido. & \\footnotesize Esfuerzo claro, trabajo más allá de lo solicitado. & \\cellcolor{gray!15}\\textbf{9.5}\\newline \\footnotesize Dedicación sobresaliente y trabajo excepcional. & \\textbf{9.5}\\\\\n\\hline\n\\cellcolor{gray!25}{\\textbf{\\textbf{Documentación / Claridad}}} & & \\footnotesize Documentación mínima o inexistente. & \\footnotesize Documentación incompleta o confusa. & \\footnotesize Documentación clara y suficiente. & \\footnotesize Documentación bien presentada y detallada. & \\cellcolor{gray!15}\\textbf{10}\\newline \\footnotesize Documentación excelente y altamente profesional. & \\textbf{10}\\\\\n\\hline\n\\cellcolor{gray!25}{\\textbf{\\textbf{Funcionalidad}}} & & \\footnotesize No funciona o no cumple objetivos. & \\footnotesize Funciona de forma parcial. & \\footnotesize Funciona correctamente. & \\footnotesize Funciona con mejoras o funcionalidades extra. & \\cellcolor{gray!15}\\textbf{9}\\newline \\footnotesize Funciona perfectamente y supera expectativas. & \\textbf{9}\\\\\n\\hline\n\\end{tabular}\n\\endgroup{}\n\\end{table}\n\n\\vspace{0.3cm}\\textbf{Puntuación final: } 9 / 10\\newline \\textbf{Equivalente sobre 60: } 54 / 60\n\n# Comentarios\n\n\n\nHas abusado mucho de la notación para redefinir el estilo predeterminado de las etiquetas. Es mejor utilizar siempre clases e ID. Muy buen uso de los selectores por propiedad y el pseudoselector de el link.\n\nNo has usado ni una clase en toda la tarea.\n\n\n---\n\nDominio completo de propiedades CSS, pero todavía tienes margen de mejora en el uso de selectores básicos.\n\n\n", + "markdown": "---\ncache: false\nformat:\n pdf:\n pdf-engine: xelatex\n toc: false\n number-sections: false\nexecute:\n echo: false\n warning: false\n message: false\nheader-includes:\n - \\usepackage{array}\n - \\usepackage{colortbl}\n - \\usepackage{xcolor}\n - \\usepackage{longtable}\n - \\renewcommand{\\arraystretch}{1.4}\n---\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n# Rúbrica de Evaluación\n\n**Tarea:** Ejecicios JS \n**Alumno:** Daniel Zanon Barney\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n\\begin{table}[!h]\n\\centering\\begingroup\\fontsize{7}{9}\\selectfont\n\n\\begin{tabular}{|>{\\centering\\arraybackslash}p{2cm}|>{\\centering\\arraybackslash}p{0.5cm}|>{\\centering\\arraybackslash}p{2.0cm}|>{\\centering\\arraybackslash}p{2.0cm}|>{\\centering\\arraybackslash}p{2.0cm}|>{\\centering\\arraybackslash}p{2.0cm}|>{\\centering\\arraybackslash}p{2.0cm}|>{\\centering\\arraybackslash}p{1.4cm}|}\n\\hline\n\\cellcolor{gray!35}{\\textbf{\\textbf{Criterio}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{N/A}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Deficiente}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Insuficiente}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Aceptable}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Bueno}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Excelente}}} & \\cellcolor{gray!35}{\\textbf{\\textbf{Puntuación}}}\\\\\n\\hline\n\\cellcolor{gray!25}{\\textbf{\\textbf{Diseño}}} & \\cellcolor{gray!15}\\textbf{N/A} & & & & & & —\\\\\n\\hline\n\\cellcolor{gray!25}{\\textbf{\\textbf{Programación}}} & & \\footnotesize Código incompleto o con errores graves. & \\footnotesize Código funcional parcialmente y/o con errores importantes. & \\cellcolor{gray!15}\\textbf{6}\\newline \\footnotesize Código funcional y adecuado a la tarea. & \\footnotesize Código bien estructurado con mejoras respecto a lo exigido. & \\footnotesize Código impecable, eficiente y muy bien organizado. & \\textbf{6}\\\\\n\\hline\n\\cellcolor{gray!25}{\\textbf{\\textbf{Esfuerzo e implicación}}} & & \\footnotesize Bajo esfuerzo o dedicación mínima. & \\footnotesize Esfuerzo adecuado pero limitado. & \\footnotesize Esfuerzo notable, cumple con lo requerido. & \\cellcolor{gray!15}\\textbf{7}\\newline \\footnotesize Esfuerzo claro, trabajo más allá de lo solicitado. & \\footnotesize Dedicación sobresaliente y trabajo excepcional. & \\textbf{7}\\\\\n\\hline\n\\cellcolor{gray!25}{\\textbf{\\textbf{Documentación / Claridad}}} & & \\footnotesize Documentación mínima o inexistente. & \\footnotesize Documentación incompleta o confusa. & \\footnotesize Documentación clara y suficiente. & \\cellcolor{gray!15}\\textbf{7}\\newline \\footnotesize Documentación bien presentada y detallada. & \\footnotesize Documentación excelente y altamente profesional. & \\textbf{7}\\\\\n\\hline\n\\cellcolor{gray!25}{\\textbf{\\textbf{Funcionalidad}}} & & \\footnotesize No funciona o no cumple objetivos. & \\footnotesize Funciona de forma parcial. & \\footnotesize Funciona correctamente. & \\cellcolor{gray!15}\\textbf{8.5}\\newline \\footnotesize Funciona con mejoras o funcionalidades extra. & \\footnotesize Funciona perfectamente y supera expectativas. & \\textbf{8.5}\\\\\n\\hline\n\\end{tabular}\n\\endgroup{}\n\\end{table}\n\n\\vspace{0.3cm}\\textbf{Puntuación final: } 7.12 / 10\\newline \\textbf{Equivalente sobre 60: } 42.8 / 60\n\n# Comentarios\n\n\n\nEn el ejercicio 3 se debeía de imprimir también el array por pantalla, en el código subido a GitHub, lo has encapsulado dentro de la función `arr2`. No se deben encapuslar los array en funciones.\n\nEl ejercicio 7 está mal: el metodo `.push()` de los arrays devuelve la nueva longitud del array. En tu código en la línea 21: `const arrFinal =arrCubosFiltrados.push(21);` está añadiendo el número `21` al array `arrCubosFiltrados` mientras que `arrFinal` se corresponde con la longitud de `arrCubosFiltrados` (incluyendo el 21). La respuesta correcta era `let arrFinal = [...arrCubosFiltrados, 21];`\n\nEn lo que respecta al formato del documento, es convención en JS insertar un espacio entre los operadores: NO `x%2==0` sino `x % 2 === 0`. \n\n---\n\nEn general bien, todavía hay margen de mejora en lo que respecta al uso de los array, muy buen uso de las funciones `filter` y `map`.\n\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/_quarto.yml b/_quarto.yml index e26bc9c..fa4635b 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -70,6 +70,12 @@ website: contents: - pages/Bloque3/ReactI.qmd - pages/Bloque3/ps.qmd + + - section: "Semana 9" + contents: + - pages/Bloque3/Intermedio.qmd + - pages/Bloque3/MARef.qmd + - text: "Próximamente..." diff --git a/docs/about.html b/docs/about.html index e7697c7..65031cc 100644 --- a/docs/about.html +++ b/docs/about.html @@ -2,7 +2,7 @@ - + @@ -37,9 +37,9 @@ - - - + + + diff --git a/docs/about.pdf b/docs/about.pdf index 263416a390b813de2745cbc4c6ecaf37e8319ec9..fe9334c991ece5f6f6892d02953d151f924c0cae 100644 GIT binary patch delta 136 zcmcaxakpYaf~k(Nfr){ok(r@|wt=C#fq}ZFg1&Elic4Zis)B}#m63swnE_nM<{s14 ztZpujhL+|Q&Q3-KCQc@(L6 BBXa-% diff --git a/docs/index.html b/docs/index.html index dc62c2d..ad6869c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2,7 +2,7 @@ - + @@ -37,9 +37,9 @@ - - - + + + @@ -480,6 +480,29 @@ Proyecto Subsistema + + + + diff --git a/docs/index.pdf b/docs/index.pdf index 2f42f0e012a0c54c5f36631ba65a3d5921988a41..038dc75d3af40f95a187e6731f55ac55f4b3e982 100644 GIT binary patch delta 139 zcmdnEnQ7x@rVYBiI>rVj29`!Y57rzWFIGi6yBD8ZK5w21aHEa3z}~ zd(UyXS(=%eJ6akTI2pTHIJ-H!Il7veSUMV*8M_*|S-3cx+bP%(RuVf|(Nb=6_Y5^g E02t~c_W%F@ delta 139 zcmdnEnQ7x@rVYBiI);X(Mg|6^rWV=;hUx|e>Y57rzWFIGi6yBD8ZK5w21aHEa3z}~ zd(UyX89BKaIT@H4Te=!MIy<>pSXvl48o5{+IJ-JKyBZrB+9}u&RuVf|(Nb=6_Y5^g E02q2B=Kufz diff --git a/docs/pages/Bloque1/MAcss.html b/docs/pages/Bloque1/MAcss.html index 5eb9274..e806338 100644 --- a/docs/pages/Bloque1/MAcss.html +++ b/docs/pages/Bloque1/MAcss.html @@ -2,7 +2,7 @@ - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -539,7 +562,7 @@

MA: Selectores y Pseudoselectores

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque1/MAcss.pdf b/docs/pages/Bloque1/MAcss.pdf index 369fbd0ccb8703f88192e64c38c1203fad22cfa6..db7d4163fb5bac9b8ddad20b411e47cc7a1e7570 100644 GIT binary patch delta 117 zcmbPxm~rl5#tj(}oW=$w29`!fCZ>}MBcu?#%~K-wu)8@Ko0*y!IvSW;7#O;lyO - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -539,7 +562,7 @@

MA: Mas HTML

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque1/MAhtml2.pdf b/docs/pages/Bloque1/MAhtml2.pdf index d6ac7a2c6476618e0d14c3e18a8021657ee813d3..1200a72a835f59b8c20e165a702c7033e1575489 100644 GIT binary patch delta 118 zcmZ2>h;i8=#tk#VIE@WV3@nX|OpPZm43k3eHXjN5%i-o`=44=K;Am)OXlP()XlUVL ih;i8=#tk#VI1LR=jSLKojSMC)43k3eHXjN5%i-qa=w#sNY+>kPV(DUTX6fW& iY-nU)Vr<~-W@+hY>gsH#U_)3*?Bt7za+_5X7#RW4*B_q% diff --git a/docs/pages/Bloque1/bloque1.html b/docs/pages/Bloque1/bloque1.html index e76dffd..74040b5 100644 --- a/docs/pages/Bloque1/bloque1.html +++ b/docs/pages/Bloque1/bloque1.html @@ -2,7 +2,7 @@ - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -546,7 +569,7 @@

Bloque I Introducción

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque1/bloque1.pdf b/docs/pages/Bloque1/bloque1.pdf index 8dcd0eee660a0788d38b05d3c3efbea882caa1ef..6f8c0bd522cd42a3565b54c376b04f5803f7856a 100644 GIT binary patch delta 118 zcmZ4ZgK^;x#tk6_oW=$w29`!f1}2kZ3#1Ud%?$;rTy6#~&KBm*#-`3LjwWsfMvfLH h&Th`8jzA3-uI2_N7Iq3Ygq6fj7ATb8%vCMU2mp(z9#a4S delta 118 zcmZ4ZgK^;x#tk6_oQ8&`Mg|5(CWez^3#1Ud%?$;rTy92AZpJQ-u11zlmWBpKPEMAl ij%J2tW~Pp&=B_RVmL_%zHiVVLP8KMX-^^7l&Ika1L>?gk diff --git a/docs/pages/Bloque1/css.html b/docs/pages/Bloque1/css.html index 132d66a..c5ae889 100644 --- a/docs/pages/Bloque1/css.html +++ b/docs/pages/Bloque1/css.html @@ -2,7 +2,7 @@ - + @@ -73,9 +73,9 @@ - - - + + + @@ -516,6 +516,29 @@ Proyecto Subsistema + + + + @@ -602,7 +625,7 @@

CSS

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque1/css.pdf b/docs/pages/Bloque1/css.pdf index 0a84743c72be6b4fc30e3fc09569d6a4964e9573..c50b9d917f8c55d9e92ee02e2abbb92881a3b7f7 100644 GIT binary patch delta 143 zcmex$nB~`DmWC~i_98mQ1||lUM#hE)+6IQ|1_tVy3i`hJDK3d6sR|k{Rz?O!W(II2 z+p|R&?{c{rS(v&S7&sc4Ihh(68w2%PxH`MKm|2*cS{RyJx*FOk*br6{J6SM7Zu=T} HMn5J1g5)EC delta 143 zcmex$nB~`DmWC~i_98llhNeaa2FAul+6IQ|1_tVy3i`hJDK3d6sR|k{Rz?O!W(II2 z+p|R&?{c|0yE+;vS Ic}71b0F-ef=Kufz diff --git a/docs/pages/Bloque1/css_p.html b/docs/pages/Bloque1/css_p.html index 871218c..09d6513 100644 --- a/docs/pages/Bloque1/css_p.html +++ b/docs/pages/Bloque1/css_p.html @@ -6,8 +6,8 @@ - - + + diff --git a/docs/pages/Bloque1/ehtml.html b/docs/pages/Bloque1/ehtml.html index 798fca3..dcfa1c6 100644 --- a/docs/pages/Bloque1/ehtml.html +++ b/docs/pages/Bloque1/ehtml.html @@ -6,8 +6,8 @@ - - + + diff --git a/docs/pages/Bloque1/entorno-reveal.html b/docs/pages/Bloque1/entorno-reveal.html index d6c306d..66e98ec 100644 --- a/docs/pages/Bloque1/entorno-reveal.html +++ b/docs/pages/Bloque1/entorno-reveal.html @@ -6,8 +6,8 @@ - - + + diff --git a/docs/pages/Bloque1/entorno.html b/docs/pages/Bloque1/entorno.html index f14ce9d..78cdec5 100644 --- a/docs/pages/Bloque1/entorno.html +++ b/docs/pages/Bloque1/entorno.html @@ -2,7 +2,7 @@ - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -576,7 +599,7 @@

Preparación del entorno de trabajo

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque1/entorno.pdf b/docs/pages/Bloque1/entorno.pdf index 6fa045422ae390fae04f562e817ea78437905c08..9a62adea01d02438080aa8d8f6edf8abe98724ed 100644 GIT binary patch delta 140 zcmezVSpEBB^@bM47N!>F7M2#)7Pc1l7LF~PmmhH&8<-ea8W|gzOuzGpQwqV|{{IoD z0*{-MnWdYnskxz>fuV`BiKUyFnX!w7k(r^Hv7xcExvR0Af(>CMvC|Vp80EG%zvnDr F0s#NOC(Zx> delta 140 zcmezVSpEBB^@bM47N!>F7M2#)7Pc1l7LF~PmmhH&8k!mz7#N$FPrvhsQwqV|{{IoD z0*{-Ek+YGdtD&W-qk*NXk-4#nn~8~;k&CgJi>Z^Lql>GZf(>CMvC|Vp80EG%zvnDr F0ssT}C=37q diff --git a/docs/pages/Bloque1/html.html b/docs/pages/Bloque1/html.html index 0266804..b4caa4c 100644 --- a/docs/pages/Bloque1/html.html +++ b/docs/pages/Bloque1/html.html @@ -2,7 +2,7 @@ - + @@ -73,9 +73,9 @@ - - - + + + @@ -516,6 +516,29 @@ Proyecto Subsistema + + + + @@ -608,7 +631,7 @@

HTML

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque1/html.pdf b/docs/pages/Bloque1/html.pdf index bac83620c9735ed9cf87ad59a0eee0a7a70f51ef..10ece1255a33d3594d0de8ddf4516a034e24eff8 100644 GIT binary patch delta 143 zcmZo^*KKLnZD?U^VQOJ+VQFD)VQXP;;b`G(;o8EjV$Er6U}9itWMpVQUDujh3c=kT zV9kAr#m&^n*x1y-(!j~U%)r9L*v!?^!r0Ws(!|8X+1bd@($r4DhOm;@$p-9l+uIzt H|1kjoD77ON delta 143 zcmZo^*KKLnZD?U^VQOJ+VQFD)VQXP;;b`G(;o8EjV$Er2Xli6&U}S1MUDujh3c=kT zV9kAr#m&jW)XB-r3`iOqI=Yz~8@d`=8oC;o8akUgS~!~;+9}u&RuVhefL(5Tn*;Yh FCIChkBdP!Z diff --git a/docs/pages/Bloque1/t1.html b/docs/pages/Bloque1/t1.html index 3f8cd96..5389a96 100644 --- a/docs/pages/Bloque1/t1.html +++ b/docs/pages/Bloque1/t1.html @@ -2,7 +2,7 @@ - + @@ -73,9 +73,9 @@ - - - + + + @@ -516,6 +516,29 @@ Proyecto Subsistema + + + + @@ -574,7 +597,7 @@

T1: Web de HL I

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque1/t1.pdf b/docs/pages/Bloque1/t1.pdf index 585cdeab0ebd29d17a8c95e3a20bca385f1c7360..67a7e71ea5a32cd9f441ad923e81ac52611316a6 100644 GIT binary patch delta 116 zcmaFd!}Pd^X+vc-hp~Z)fu)g=@#My8X*g%|l4@&CHw!0cR|_{M12V|t delta 116 zcmaFd!}Pd^X+vc-hoPaVk%57+!Q{qjX*g%|l4@&CH%m)%b2npCV`FDiXERenGb2|s hClhC5b8|B{OJ_?{b2|ka!b)N%8@eiNc5Rho1OQc99vJ`t diff --git a/docs/pages/Bloque1/t1a.html b/docs/pages/Bloque1/t1a.html index ed0bc20..e667795 100644 --- a/docs/pages/Bloque1/t1a.html +++ b/docs/pages/Bloque1/t1a.html @@ -2,7 +2,7 @@ - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -539,7 +562,7 @@

TA1: Mi CV I

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque1/t1a.pdf b/docs/pages/Bloque1/t1a.pdf index f007ad45a7a94bcfc8542411fb373543672b2564..8a109c10d07a8d6d1f36be15bb07a776d487844c 100644 GIT binary patch delta 138 zcmaFAjPd<4#tnSlI>rVj29`!fMi$xzhUx|e>Y57rzWFIGi6yBD8ZK5w21aHEa3!0q zyuY%!8MzubyPBFfy0{vd85Y57rzWFIGi6yBD8ZK5w21aHEa3!0q zyuY%!8CaScyO - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -539,7 +562,7 @@

T2: Web de HL II

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque1/t2.pdf b/docs/pages/Bloque1/t2.pdf index 3f2908050703950fb2b1c08fae6a2906dfe797d9..f8f2f58062a9dfec40c0494798c7a7c7f3721417 100644 GIT binary patch delta 138 zcmdmek#YA$#tnbsw2ci+3@nX|jZL%-4Al(`)HN0Kee+XX5=&AQG+eBV42;YSU`jTt z$7^%AIhmR|nHU+lIvX3ini@O0nwU778oC-A8yi}fS(uwS+9}u&RuVh;qKy3J?ddFx E01bH~b^rhX delta 138 zcmdmek#YA$#tnbsv<(eSjSLKoO--~74Al(`)HN0Kee+XX5=&AQG+eBV42;YSU`jTt z$7^%AnYo&nT9~*R8#*}~m^nMTI6E6VnLC=gxfz)oI~f`q*(ul%RuVh;qKy3J?ddFx E02>=4+5i9m diff --git a/docs/pages/Bloque1/t2a.html b/docs/pages/Bloque1/t2a.html index 93cfb6d..7e058ee 100644 --- a/docs/pages/Bloque1/t2a.html +++ b/docs/pages/Bloque1/t2a.html @@ -2,7 +2,7 @@ - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -539,7 +562,7 @@

TA2: Mi CV II

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque1/t2a.pdf b/docs/pages/Bloque1/t2a.pdf index f8a9f6639f381ce4095ffd2aae6fcb4cf68a081d..0fee716daa1de4922a6299d1f4685450ff43eb96 100644 GIT binary patch delta 131 zcmdn7fpNzM#tr-Zb&L&63@nWdP0h6p4Al(`)HN0Kee+XX5=&AQG+eBV42;YS;7T^X y_7`AxHnuQwF*kK~vov=xb~7+?G%#|rG_`bdbult>=_1 diff --git a/docs/pages/Bloque2/MAclases.html b/docs/pages/Bloque2/MAclases.html index 5bede03..61c3628 100644 --- a/docs/pages/Bloque2/MAclases.html +++ b/docs/pages/Bloque2/MAclases.html @@ -2,7 +2,7 @@ - + @@ -73,9 +73,9 @@ - - - + + + @@ -516,6 +516,29 @@ Proyecto Subsistema + + + + @@ -596,7 +619,7 @@

MA: Clases ES6

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque2/MAclases.pdf b/docs/pages/Bloque2/MAclases.pdf index 228e29c5c12dccb2458a1be966af54d47128f68c..1c2e894e3d1c7e77418907ad8d7729eb34642b09 100644 GIT binary patch delta 139 zcmaEMjrrL%<_&Kj=olNA7+4ya7#nFD7^)i>sB0?d`{t*(B$lKqXt-Dz85o%vz?E#4 zeE6N+&CJZn(b37#$-vRl#m&gf)Y;6$*~!e<+||g;#L&gf)K0;Mu#(uxiAUr&m%jYS F2mmDrC%^yz delta 139 zcmaEMjrrL%<_&Kj=olKB8W|Xvn3`)F7^)i>sB0?d`{t*(B$lKqXt-Dz85o%vz?E#4 zeE6N+&A{B!(#+h|#M#Bw(%jt9(b>Yp+|<#)%*oWv&B)Qr(oVsKu#(uxiAUr&m%jYS F2ml$JC!hcT diff --git a/docs/pages/Bloque2/intensivo.html b/docs/pages/Bloque2/intensivo.html index 9a7446d..4859f52 100644 --- a/docs/pages/Bloque2/intensivo.html +++ b/docs/pages/Bloque2/intensivo.html @@ -2,7 +2,7 @@ - + @@ -73,9 +73,9 @@ - - - + + + @@ -516,6 +516,29 @@ Proyecto Subsistema + + + + @@ -647,7 +670,7 @@

Repaso Intensivo JS

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque2/intensivo.pdf b/docs/pages/Bloque2/intensivo.pdf index a7dd13ebbe15f392bad1f92e628e5de5420fba19..dfa7901c9731e47b6c923555dce360f75234be52 100644 GIT binary patch delta 136 zcmZp@#nO6 - - + + diff --git a/docs/pages/Bloque2/jsI.html b/docs/pages/Bloque2/jsI.html index 4663e58..3c362a9 100644 --- a/docs/pages/Bloque2/jsI.html +++ b/docs/pages/Bloque2/jsI.html @@ -2,7 +2,7 @@ - + @@ -38,9 +38,9 @@ - - - + + + @@ -306,7 +306,7 @@

Introducción a JS

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque2/jsI.pdf b/docs/pages/Bloque2/jsI.pdf index 5ec673c69c60a61a4fee6367cfcd9cdcc63a6fd7..a86934cadd670fe009d8cc0962eb07ca955c121d 100644 GIT binary patch delta 118 zcmezTgz57WrVVUsIgJfW3@nX|P0S|qua!dZHXE%qW_B|*aWgP9ak6xDvNW)Cax!x> jGBPrEHg|J#F}5&sF|)K&upz7@c5-5<{N_^|Rx$zrxh^1Y delta 118 zcmezTgz57WrVVUsISma>jSLJ-3@j(}ua!dZHXE%qW_B}hF*7wVaddJsay2zHcQtl# jHF0*da5FMBbak{eHnFr*upz7@c5-5<{N_^|Rx$zrv;81j diff --git a/docs/pages/Bloque2/ti.html b/docs/pages/Bloque2/ti.html index 3af7f6b..ab80537 100644 --- a/docs/pages/Bloque2/ti.html +++ b/docs/pages/Bloque2/ti.html @@ -2,7 +2,7 @@ - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -555,7 +578,7 @@

TI: Ejercicios JS

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque2/ti.pdf b/docs/pages/Bloque2/ti.pdf index e6f447b0cb5258033e7dc75eafd1d9a5a6ace815..505ca1a38d14b605d76c80d980da9ab48eb8f4f7 100644 GIT binary patch delta 132 zcmX@~nd#7HrVWx?b&L&63@nX|P0h3o4Al(`)HN0Kee+XX5=&AQG+eBV42;YS;7T^T zZY^hWb~H70G<7vHaJF!EHgGgCcQrFHaB_1sGHZU-@uv4%hq-68|?S~lwT(cud diff --git a/docs/pages/Bloque2/tia.html b/docs/pages/Bloque2/tia.html index 296d40d..3b6088e 100644 --- a/docs/pages/Bloque2/tia.html +++ b/docs/pages/Bloque2/tia.html @@ -2,7 +2,7 @@ - + @@ -73,9 +73,9 @@ - - - + + + @@ -516,6 +516,29 @@ Proyecto Subsistema + + + + @@ -598,7 +621,7 @@

TAI: La objetización de las personas

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque2/tia.pdf b/docs/pages/Bloque2/tia.pdf index 5aa7431b0e25b7e02161db62099895318780f1d5..5386b5f9bb01343bbf41b3b2300cc34d3df9e9a4 100644 GIT binary patch delta 111 zcmZo#$K14zd4u~oPGbWT14| - + @@ -73,9 +73,9 @@ - - - + + + @@ -516,6 +516,29 @@ Proyecto Subsistema + + + + @@ -597,7 +620,7 @@

DOM

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque3/DOM.pdf b/docs/pages/Bloque3/DOM.pdf index bbd69c963a2f673d507bac18462101997fedab0b..ed37bbcbce33f8758075e2e625efde88bb0a5504 100644 GIT binary patch delta 139 zcmaFc#Qe62dBcL8I>rVj29`#q#^%}vhUx|e>Y57rzWFIGi6yBD8ZK5w21aHEa3!11 z>?~n*GjnyaFf(Y57rzWFIGi6yBD8ZK5w21aHEa3!11 z>?~n*Gcq?eF*G-{urM~VaJ6tUaCNaTGB + + + + + + + + + +React III – Training Center SW + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ + +
+
+

React III

+

Controlled fields, useEffect

+
+ + + +
+ +
+
Autor/a
+
+

Javier Ribal del Río

+
+
+ +
+
Fecha de publicación
+
+

27 de febrero de 2026

+
+
+ +
+
Fecha de última modificación
+
+

4 de marzo de 2026

+
+
+ +
+ + + +
+ + +

Contenido

+
    +
  • Controlled Inputs
  • +
  • Concepto de Hook
  • +
  • Hook useEffect
  • +
  • Introducción a API para la descarga de datos
  • +
+
+

Controlled Inputs

+
+

Motivación

+

Hasta ahora se ha trabajado con eventos capturando acciones del usuario.

+

Sin embargo, al trabajar con formularios surge una cuestión fundamental:

+
+

¿Quién controla el valor del input?
+¿El DOM o React?

+
+

Recordemos que en HTML puro o, el valor de un <input> está gestionado directamente por el DOM.

+

En React, podemos hacer que el valor del input esté controlado por el estado del componente.

+

A esto lo llamamos controlled input.

+
+
+

¿Qué es un controlled input?

+

Un controlled input es un elemento de formulario cuyo valor:

+
    +
  • Está almacenado en el estado del componente
  • +
  • Se actualiza mediante un evento (onChange)
  • +
  • Se renderiza utilizando ese mismo estado
  • +
+

Única fuente de verdad (single source of truth).

+
+
+

Estructura del componente controlled

+
import { useState } from "react";
+function FormularioNombre() {
+
+  const [nombre, setNombre] = useState("");
+
+  function manejarCambio(event) {
+    setNombre(event.target.value);
+  }
+
+  return (
+    <div>
+      <input type="text" 
+       value={nombre}
+        onChange={manejarCambio}
+      />
+      <p>El nombre introducido es: {nombre}</p>
+    </div>
+  );
+}
+
+

Análisis del ejemplo

+

El valor del input se sincroniza con el estado

+
    +
  1. Declaramos una variable de estado: nombre
  2. +
  3. Asociamos el atributo value del input a ese estado
  4. +
  5. Capturamos el evento onChange
  6. +
  7. Actualizamos el estado con setNombre
  8. +
+

Cada vez que el estado cambia: El componente se vuelve a ejecutar El JSX se vuelve a generar El valor del input se sincroniza con el estado

+
+
+
+

Ejemplo Formulario

+
import { useState } from "react";
+
+function FormularioSimple() {
+
+  const [email, setEmail] = useState("");
+
+  function handleChange(event) {
+    setEmail(event.target.value);
+  }
+
+  function handleSubmit(event) {
+    event.preventDefault();   // Evita la recarga del navegador
+
+    console.log("Formulario enviado");
+    console.log("Email:", email);
+
+    setEmail("");  // Limpieza opcional del campo
+  }
+
+  return (
+    <form onSubmit={handleSubmit}>
+      <input 
+        type="email"
+        value={email}
+        onChange={handleChange}
+      />
+      <button type="submit">Enviar</button>
+    </form>
+  );
+}
+

Referencia: https://es.react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable

+
+
+
+

Hooks (Repaso)

+
    +
  • Función especial que permite modificar las propiedades internas de los componentes
  • +
  • Características avanzadas
  • +
  • Modificación del life-cycle
  • +
  • Normalmente forma use____
  • +
+
+
+

useEffect

+
    +
  • useEffect es un Hook que permite ejecutar efectos secundarios dentro de un componente funcional.
  • +
  • Un efecto secundario es cualquier operación que no sea simplemente devolver JSX (por ejemplo: peticiones a un servidor, temporizadores, suscripciones).
  • +
  • Se ejecuta después de que el componente se renderiza en el DOM.
  • +
+
+

Métodos de uso de useEffect

+
+

1. Sin array de dependencias

+
useEffect(() => {
+  console.log("Se ejecuta en cada render");
+});
+

Comportamiento:

+
    +
  • Se ejecuta después de cada renderizado.
  • +
  • No existe control sobre la frecuencia.
  • +
  • Puede generar bucles si modifica estado sin control.
  • +
+

Interpretación conceptual:

+

El efecto acompaña siempre al render.

+
+
+

2. Con array vacío

+
useEffect(() => {
+  console.log("Se ejecuta solo una vez");
+}, []);
+

Comportamiento:

+
    +
  • Se ejecuta únicamente tras el primer render.
  • +
  • Equivalente conceptual al “montaje” del componente.
  • +
+

Uso habitual:

+
    +
  • Peticiones a servidor
  • +
  • Inicializaciones
  • +
  • Suscripciones
  • +
+

Interpretación conceptual:

+

El efecto ocurre una única vez al crear el componente.

+
+
+

3. Con dependencias específicas

+
useEffect(() => {
+  console.log("Se ejecuta cuando cambia contador");
+}, [contador]);
+

Comportamiento:

+
    +
  • Se ejecuta tras el primer render.
  • +
  • Se vuelve a ejecutar cuando cambia alguna variable del array.
  • +
+

Interpretación conceptual:

+

El efecto depende del estado indicado.

+

React compara el valor anterior con el nuevo y decide si debe ejecutar el efecto.

+
+
+
+
+

fetch()

+

Hasta ahora nuestros componentes eran completamente locales.

+

Sin embargo, en aplicaciones reales necesitamos:

+
    +
  • Descargar datos
    +
  • +
  • Conectarnos a servidores
    +
  • +
  • Trabajar con APIs externas
  • +
+

Para ello utilizamos fetch().

+
+

Ejemplo mínimo de fetch

+
fetch("https://pokeapi.co/api/v2/pokemon/1")
+  .then(response => response.json())
+  .then(data => console.log(data));
+

Utiliza las Promises

+

Interpretación simple:

+
    +
  1. Se hace una petición a una URL
    +
  2. +
  3. Se transforma la respuesta a formato JSON
    +
  4. +
  5. Se accede a los datos
  6. +
+
+
+

fetch() dentro de useEffect

+

En React, lo habitual es realizar la descarga cuando el componente se monta.

+

Para ello:

+
    +
  • Utilizamos useEffect
  • +
  • Añadimos array vacío []
  • +
  • Guardamos los datos en el estado
  • +
+
+
+

Ejemplo integrado

+
import { useState, useEffect } from "react";
+
+function Pokemon() {
+
+  const [pokemon, setPokemon] = useState(null);
+
+  useEffect(() => {
+
+    fetch("https://pokeapi.co/api/v2/pokemon/1")
+      .then(response => response.json())
+      .then(data => setPokemon(data));
+
+  }, []);
+
+  if (!pokemon) return <p>Cargando...</p>;
+
+  return (
+    <div>
+      <h2>{pokemon.name}</h2>
+      <img 
+        src={pokemon.sprites.front_default} 
+        alt={pokemon.name} 
+      />
+    </div>
+  );
+}
+
+
+

Flujo conceptual

+
    +
  1. Render inicial
    +
  2. +
  3. Se ejecuta useEffect
    +
  4. +
  5. Se lanza la petición
    +
  6. +
  7. Se actualiza el estado
    +
  8. +
  9. Nuevo render con los datos
  10. +
+
+
+

Advertencia importante

+

Si eliminamos el array vacío:

+
useEffect(() => {
+  fetch("https://pokeapi.co/api/v2/pokemon/1")
+    .then(res => res.json())
+    .then(data => setPokemon(data));
+});
+

El efecto se ejecutará en cada render.

+

Como actualizar estado provoca render, se generará un bucle infinito.

+

useEffect conecta React con el exterior.
+fetch() permite traer datos del exterior.
+El estado vuelve a controlar el render.

+

En la siguiente sección formalizaremos esto utilizando async / await.

+
+
+
+

async y await

+

Hasta ahora hemos utilizado fetch() con encadenamiento.

+

Existe una forma más clara y estructurada de escribir código asíncrono:

+
    +
  • async
  • +
  • await
  • +
+

Su objetivo es hacer que el código sea más legible.

+
+

¿Qué significa async?

+
    +
  • Se coloca delante de una función
  • +
  • Indica que la función trabajará con operaciones asíncronas
  • +
+
async function ejemplo() {
+  console.log("Función asíncrona");
+}
+
+
+

¿Qué significa await?

+
    +
  • Solo puede utilizarse dentro de una función async
  • +
  • Detiene la ejecución hasta que la operación finaliza
  • +
  • Hace que el código se lea de forma secuencial
  • +
+
+
+

Ejemplo básico con fetch

+
async function obtenerPokemon() {
+
+  const response = await fetch(
+    "https://pokeapi.co/api/v2/pokemon/1"
+  );
+
+  const data = await response.json();
+
+  console.log(data);
+}
+

Interpretación conceptual:

+
    +
  1. Se realiza la petición
  2. +
  3. Se espera la respuesta
  4. +
  5. Se transforma a JSON
  6. +
  7. Se trabaja con los datos
  8. +
+

El código se lee de arriba hacia abajo.

+
+
+

async / await dentro de useEffect

+

En React, lo habitual es declarar una función interna y ejecutarla.

+
+
+

Ejemplo completo

+
import { useState, useEffect } from "react";
+
+function Pokemon() {
+
+  const [pokemon, setPokemon] = useState(null);
+
+  useEffect(() => {
+
+    async function fetchData() {
+
+      const response = await fetch(
+        "https://pokeapi.co/api/v2/pokemon/1"
+      );
+
+      const data = await response.json();
+
+      setPokemon(data);
+    }
+
+    fetchData();
+
+  }, []);
+
+  if (!pokemon) return <p>Cargando...</p>;
+
+  return (
+    <div>
+      <h2>{pokemon.name}</h2>
+      <img 
+        src={pokemon.sprites.front_default} 
+        alt={pokemon.name} 
+      />
+    </div>
+  );
+}
+
+
+

¿Por qué no hacer directamente?

+
useEffect(async () => {
+  ...
+}, []);
+

Porque useEffect no debe recibir una función asíncrona directamente.

+

Por eso declaramos la función dentro y luego la ejecutamos.

+
+
+

Flujo mental con async / await

+
    +
  1. Render inicial
    +
  2. +
  3. Se ejecuta useEffect
    +
  4. +
  5. Se llama a la función asíncrona
    +
  6. +
  7. await espera la respuesta
    +
  8. +
  9. Se actualiza el estado
    +
  10. +
  11. Nuevo render
  12. +
+

async / await no cambia lo que hace el programa.

+

Solo cambia la forma de escribirlo:

+

Más claro.
+Más estructurado.
+Más fácil de mantener.

+
+
+
+

Ejemplo con la Pokeapi

+

Poke-API

+

Download Code

+ + +
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/docs/pages/Bloque3/Intermedio.pdf b/docs/pages/Bloque3/Intermedio.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0e6a7f18f9d7acc24e25b8254a5abde09c90c0e9 GIT binary patch literal 83354 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 literal 0 HcmV?d00001 diff --git a/docs/pages/Bloque3/MARef.html b/docs/pages/Bloque3/MARef.html new file mode 100644 index 0000000..aa506de --- /dev/null +++ b/docs/pages/Bloque3/MARef.html @@ -0,0 +1,1005 @@ + + + + + + + + + + +MA: Uncontrolled fields y useRef – Training Center SW + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ + +
+
+

MA: Uncontrolled fields y useRef

+
+ + + +
+ +
+
Autor/a
+
+

Javier Ribal del Río

+
+
+ +
+
Fecha de publicación
+
+

2 de marzo de 2025

+
+
+ +
+
Fecha de última modificación
+
+

4 de marzo de 2026

+
+
+ +
+ + + +
+ + +

Por el momento hemos visto dos hooks useState y useEffect, pero recordemos que en React existen más tipos de hooks que por ser menos útiles y debido a la falta de tiempo no son explicados, no obstante si hay alguno digno de mención es useRef o las referencias.

+

Una ref es una referencia mutable que permite acceder directamente a un elemento del DOM o almacenar un valor persistente sin provocar un re-render del componente. El siguiente video ilustra su uso. Es un poco largo pero sirve para repasar los otros hooks.

+
+
+

Con las ref podemos introducir los uncontrolled fields que nos permiten trabajar de otra forma con los formularios.

+
+

Se prefiere la segunda implementación (la que no utiliza referencias) sobre la primera.

+ + + +
+ +
+ + + + + \ No newline at end of file diff --git a/docs/pages/Bloque3/MARef.pdf b/docs/pages/Bloque3/MARef.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7c98c9de57d6b1e68d511760311944545634bb7f GIT binary patch literal 33614 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 - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -539,7 +562,7 @@

MA: CSS Flex y CSS

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque3/MAcss2.pdf b/docs/pages/Bloque3/MAcss2.pdf index 0690d19199c921dbc53f2ae93ee9ead12298d816..785ce722c1294620f7d069eabeacc8b9aedf2e0e 100644 GIT binary patch delta 132 zcmX?hit*Sf#tjdmb&L&63@nXIjZC!-4Al(`)HN0Kee+XX5=&AQG+eBV42;YS;7T_0 y#Jp#BcC$1va0FsAQ!__nM-vw(X9E*cOE*I&Lo+95OG7g|1sg(2Hru6eFaiKyts!^- delta 132 zcmX?hit*Sf#tjdmbqoznjSLJ-jf}Jn4Al(`)HN0Kee+XX5=&AQG+eBV42;YS;7T_0 z#Jp#BHZ(M{aCUVucQbNwb~LkawJ>$HG_f=`b8)h8b1`vswo|Ynq-3*Q3I`(qaepEt diff --git a/docs/pages/Bloque3/PokeAPI-Example.zip b/docs/pages/Bloque3/PokeAPI-Example.zip new file mode 100644 index 0000000000000000000000000000000000000000..430af25063879f9fdfd7228f1ad7a945fc6f2224 GIT binary patch literal 1267 zcmWIWW@Zs#U|`^2SiLYQ=2z*exVwxD411Uv7}yzP7#s@<^s?1n z3T_5QmKQ)3U?Miyw|};Qz~0~CKE;e-g43$9XD?ZGWy`9N+|?nrYrj2cbzI1JdsDlw z(v<)A3=^is>Y4H1JAUTIqP(?*ES`G%BW8==Q%`EDdSUZ!H5YeO`&;>-mV)L}GsT43 zS1tH?|NgU?~2@&{mPXAzRV>@mb#j(oY0jllAil?{jP=; zOoyG{S-oe!nBT~9;YzOWg+)ne6RyYpZpn+}KHT*n%gSQ*I?b7dP72Ixtsd%Fuob@0 z%{NG~SY72cZC#(swfZSW9$L}QTPN;0@%(#{(NCKrH|io<<6O?}YWfm8<;+>lXpsY~ zvU4q)j~Tz2YpfT0SDNYT6`q@H_bmeCLzLgDP4oSceY!v{?&}xd_>D1TWh=7IeK{{Z zS5H~LZO*>L=Vx9?eVW))S<|7dl4=Z%cCd)1$pc3p~S;yTACzlle9 z*3bL4o=z(iH!o|ru*gRvhRw0;8mH#shs!M!6TgI|yM-+H@!5A$i&c{rM?>z$7s(1= z=RGqtyj7{E%bg-M+t}GAMgP5#@scMUnau`F6juCvN2X@**vhDQg- zqf-4fi+|h;cUrbIGqvvS|9iP@JEpBGd_UFh$qnvq$6eub56EsZ-?aV@i*WKed5`Tu z$F6;fD3SZ26nb29hx0|F3jQqb1u`=(Pq$uv%AqD<#ZJqQ1`U1JVjLc`%B?XCYq4go z2<=d{JImaPNF1&*_l!4_;bwH6^;%FZ8?k zjdxG)Ri(LW+d^0UbDHG+yll_w!W-sQwU;+p)y0JW6MB{+cUtJJo0Ul5-lz@9BFnm% zWdddUMB3-uPrWWM$M?}G<#Vx_qJ@Wl`k3xrGUH^ipQ+BSKUbSlKiHQm9LO$y5qsuG z!}R|Q0p5&Ea?H324+&tQ!oUDbEeuN - + @@ -73,9 +73,9 @@ - - - + + + @@ -516,6 +516,29 @@ Proyecto Subsistema + + + + @@ -621,7 +644,7 @@

React I

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque3/ReactI.pdf b/docs/pages/Bloque3/ReactI.pdf index 67937cedb1872e932b8981536baf2acbc10314e9..2058a9cdcaddcc289242ca2086637766e396dba7 100644 GIT binary patch delta 123 zcmex-kmd71mWC~i&XSzQ1||lUMy93)(|sfvr4Zch`I3yuEN&*ICWek~W@e^FMurxq n=59`|h9;J7hK?4N&X(rRCeC&WHiVVLPIg?Zu-!tAaW@kHt^6Lx delta 123 zcmex-kmd71mWC~i&XSylhNeaa2Bsz!(|sfvr4Zch`I3yuEN;dw7H$@1mKNrwMlLSS nW^T?#rsl4$7KUbqW=>8P7G`z|HiVVLPIg?Zu-!tAaW@kHzp@_- diff --git a/docs/pages/Bloque3/dom.html b/docs/pages/Bloque3/dom.html index 3e7189b..782f064 100644 --- a/docs/pages/Bloque3/dom.html +++ b/docs/pages/Bloque3/dom.html @@ -6,8 +6,8 @@ - - + + diff --git a/docs/pages/Bloque3/intermedio.html b/docs/pages/Bloque3/intermedio.html new file mode 100644 index 0000000..803cbf9 --- /dev/null +++ b/docs/pages/Bloque3/intermedio.html @@ -0,0 +1,1039 @@ + + + + + + + + + + + + + + Training Center SW – React III + + + + + + + + + + + + + + + + +
+
+ +
+

React III

+

Controlled fields, useEffect

+ +
+
+
+Javier Ribal del Río +
+
+
+ +

2026-02-27

+
+
+ +

Contenido

+
    +
  • Controlled Inputs
  • +
  • Concepto de Hook
  • +
  • Hook useEffect
  • +
  • Introducción a API para la descarga de datos
  • +
+
+
+

Controlled Inputs

+

Motivación

+

Hasta ahora se ha trabajado con eventos capturando acciones del usuario.

+

Sin embargo, al trabajar con formularios surge una cuestión fundamental:

+
+

¿Quién controla el valor del input?
+¿El DOM o React?

+
+
+
+ +

Recordemos que en HTML puro o, el valor de un <input> está gestionado directamente por el DOM.

+

En React, podemos hacer que el valor del input esté controlado por el estado del componente.

+

A esto lo llamamos controlled input.

+
+
+ +

¿Qué es un controlled input?

+

Un controlled input es un elemento de formulario cuyo valor:

+
    +
  • Está almacenado en el estado del componente
  • +
  • Se actualiza mediante un evento (onChange)
  • +
  • Se renderiza utilizando ese mismo estado
  • +
+

Única fuente de verdad (single source of truth).

+
+
+ +

Estructura del componente controlled

+
import { useState } from "react";
+function FormularioNombre() {
+
+  const [nombre, setNombre] = useState("");
+
+  function manejarCambio(event) {
+    setNombre(event.target.value);
+  }
+
+  return (
+    <div>
+      <input type="text" 
+       value={nombre}
+        onChange={manejarCambio}
+      />
+      <p>El nombre introducido es: {nombre}</p>
+    </div>
+  );
+}
+
+
+ +

Análisis del ejemplo

+

El valor del input se sincroniza con el estado

+
    +
  1. Declaramos una variable de estado: nombre
  2. +
  3. Asociamos el atributo value del input a ese estado
  4. +
  5. Capturamos el evento onChange
  6. +
  7. Actualizamos el estado con setNombre
  8. +
+
+
+ +

Cada vez que el estado cambia: El componente se vuelve a ejecutar El JSX se vuelve a generar El valor del input se sincroniza con el estado

+
+
+ +

Ejemplo Formulario

+
import { useState } from "react";
+
+function FormularioSimple() {
+
+  const [email, setEmail] = useState("");
+
+  function handleChange(event) {
+    setEmail(event.target.value);
+  }
+
+  function handleSubmit(event) {
+    event.preventDefault();   // Evita la recarga del navegador
+
+    console.log("Formulario enviado");
+    console.log("Email:", email);
+
+    setEmail("");  // Limpieza opcional del campo
+  }
+
+  return (
+    <form onSubmit={handleSubmit}>
+      <input 
+        type="email"
+        value={email}
+        onChange={handleChange}
+      />
+      <button type="submit">Enviar</button>
+    </form>
+  );
+}
+
+
+ +

Referencia: https://es.react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable

+
+
+

Hooks (Repaso)

+
    +
  • Función especial que permite modificar las propiedades internas de los componentes
  • +
  • Características avanzadas
  • +
  • Modificación del life-cycle
  • +
  • Normalmente forma use____
  • +
+
+
+

useEffect

+
    +
  • useEffect es un Hook que permite ejecutar efectos secundarios dentro de un componente funcional.
  • +
  • Un efecto secundario es cualquier operación que no sea simplemente devolver JSX (por ejemplo: peticiones a un servidor, temporizadores, suscripciones).
  • +
  • Se ejecuta después de que el componente se renderiza en el DOM.
  • +
+
+
+ +

Métodos de uso de useEffect

+

1. Sin array de dependencias

+
useEffect(() => {
+  console.log("Se ejecuta en cada render");
+});
+

Comportamiento:

+
    +
  • Se ejecuta después de cada renderizado.
  • +
  • No existe control sobre la frecuencia.
  • +
  • Puede generar bucles si modifica estado sin control.
  • +
+

Interpretación conceptual:

+

El efecto acompaña siempre al render.

+
+
+ +

2. Con array vacío

+
useEffect(() => {
+  console.log("Se ejecuta solo una vez");
+}, []);
+

Comportamiento:

+
    +
  • Se ejecuta únicamente tras el primer render.
  • +
  • Equivalente conceptual al “montaje” del componente.
  • +
+
+
+ +

Uso habitual:

+
    +
  • Peticiones a servidor
  • +
  • Inicializaciones
  • +
  • Suscripciones
  • +
+

Interpretación conceptual:

+

El efecto ocurre una única vez al crear el componente.

+
+
+ +

3. Con dependencias específicas

+
useEffect(() => {
+  console.log("Se ejecuta cuando cambia contador");
+}, [contador]);
+

Comportamiento:

+
    +
  • Se ejecuta tras el primer render.
  • +
  • Se vuelve a ejecutar cuando cambia alguna variable del array.
  • +
+
+
+ +

Interpretación conceptual:

+

El efecto depende del estado indicado.

+

React compara el valor anterior con el nuevo y decide si debe ejecutar el efecto.

+
+
+

fetch()

+

Hasta ahora nuestros componentes eran completamente locales.

+

Sin embargo, en aplicaciones reales necesitamos:

+
    +
  • Descargar datos
    +
  • +
  • Conectarnos a servidores
    +
  • +
  • Trabajar con APIs externas
  • +
+

Para ello utilizamos fetch().

+
+
+ +

Ejemplo mínimo de fetch

+
fetch("https://pokeapi.co/api/v2/pokemon/1")
+  .then(response => response.json())
+  .then(data => console.log(data));
+

Utiliza las Promises

+
+
+ +

Interpretación simple:

+
    +
  1. Se hace una petición a una URL
    +
  2. +
  3. Se transforma la respuesta a formato JSON
    +
  4. +
  5. Se accede a los datos
  6. +
+
+
+ +

fetch() dentro de useEffect

+

En React, lo habitual es realizar la descarga cuando el componente se monta.

+

Para ello:

+
    +
  • Utilizamos useEffect
  • +
  • Añadimos array vacío []
  • +
  • Guardamos los datos en el estado
  • +
+
+
+ +

Ejemplo integrado

+
import { useState, useEffect } from "react";
+
+function Pokemon() {
+
+  const [pokemon, setPokemon] = useState(null);
+
+  useEffect(() => {
+
+    fetch("https://pokeapi.co/api/v2/pokemon/1")
+      .then(response => response.json())
+      .then(data => setPokemon(data));
+
+  }, []);
+
+  if (!pokemon) return <p>Cargando...</p>;
+
+  return (
+    <div>
+      <h2>{pokemon.name}</h2>
+      <img 
+        src={pokemon.sprites.front_default} 
+        alt={pokemon.name} 
+      />
+    </div>
+  );
+}
+
+
+ +

Flujo conceptual

+
    +
  1. Render inicial
    +
  2. +
  3. Se ejecuta useEffect
    +
  4. +
  5. Se lanza la petición
    +
  6. +
  7. Se actualiza el estado
    +
  8. +
  9. Nuevo render con los datos
  10. +
+
+
+ +

Advertencia importante

+

Si eliminamos el array vacío:

+
useEffect(() => {
+  fetch("https://pokeapi.co/api/v2/pokemon/1")
+    .then(res => res.json())
+    .then(data => setPokemon(data));
+});
+

El efecto se ejecutará en cada render.

+

Como actualizar estado provoca render, se generará un bucle infinito.

+
+
+ +

useEffect conecta React con el exterior.
+fetch() permite traer datos del exterior.
+El estado vuelve a controlar el render.

+

En la siguiente sección formalizaremos esto utilizando async / await.

+
+
+

async y await

+

Hasta ahora hemos utilizado fetch() con encadenamiento.

+

Existe una forma más clara y estructurada de escribir código asíncrono:

+
    +
  • async
  • +
  • await
  • +
+

Su objetivo es hacer que el código sea más legible.

+
+
+ +

¿Qué significa async?

+
    +
  • Se coloca delante de una función
  • +
  • Indica que la función trabajará con operaciones asíncronas
  • +
+
async function ejemplo() {
+  console.log("Función asíncrona");
+}
+
+
+ +

¿Qué significa await?

+
    +
  • Solo puede utilizarse dentro de una función async
  • +
  • Detiene la ejecución hasta que la operación finaliza
  • +
  • Hace que el código se lea de forma secuencial
  • +
+
+
+ +

Ejemplo básico con fetch

+
async function obtenerPokemon() {
+
+  const response = await fetch(
+    "https://pokeapi.co/api/v2/pokemon/1"
+  );
+
+  const data = await response.json();
+
+  console.log(data);
+}
+
+
+ +

Interpretación conceptual:

+
    +
  1. Se realiza la petición
  2. +
  3. Se espera la respuesta
  4. +
  5. Se transforma a JSON
  6. +
  7. Se trabaja con los datos
  8. +
+

El código se lee de arriba hacia abajo.

+
+
+ +

async / await dentro de useEffect

+

En React, lo habitual es declarar una función interna y ejecutarla.

+
+
+ +

Ejemplo completo

+
import { useState, useEffect } from "react";
+
+function Pokemon() {
+
+  const [pokemon, setPokemon] = useState(null);
+
+  useEffect(() => {
+
+    async function fetchData() {
+
+      const response = await fetch(
+        "https://pokeapi.co/api/v2/pokemon/1"
+      );
+
+      const data = await response.json();
+
+      setPokemon(data);
+    }
+
+    fetchData();
+
+  }, []);
+
+  if (!pokemon) return <p>Cargando...</p>;
+
+  return (
+    <div>
+      <h2>{pokemon.name}</h2>
+      <img 
+        src={pokemon.sprites.front_default} 
+        alt={pokemon.name} 
+      />
+    </div>
+  );
+}
+
+
+ +

¿Por qué no hacer directamente?

+
useEffect(async () => {
+  ...
+}, []);
+

Porque useEffect no debe recibir una función asíncrona directamente.

+

Por eso declaramos la función dentro y luego la ejecutamos.

+
+
+ +

Flujo mental con async / await

+
    +
  1. Render inicial
    +
  2. +
  3. Se ejecuta useEffect
    +
  4. +
  5. Se llama a la función asíncrona
    +
  6. +
  7. await espera la respuesta
    +
  8. +
  9. Se actualiza el estado
    +
  10. +
  11. Nuevo render
  12. +
+
+
+ +

async / await no cambia lo que hace el programa.

+

Solo cambia la forma de escribirlo:

+

Más claro.
+Más estructurado.
+Más fácil de mantener.

+
+
+

Ejemplo con la Pokeapi

+

Poke-API

+

Download Code

+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/pages/Bloque3/ps.html b/docs/pages/Bloque3/ps.html index 5c55f17..1d06ecc 100644 --- a/docs/pages/Bloque3/ps.html +++ b/docs/pages/Bloque3/ps.html @@ -2,7 +2,7 @@ - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -550,7 +573,7 @@

Proyecto Subsistema

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque3/ps.pdf b/docs/pages/Bloque3/ps.pdf index 3e8673489a24abcec48d54e38e0acd4eaab119e8..799b0d673c0e53567847745ff926b224af2b9ced 100644 GIT binary patch delta 118 zcmX@In(4@DrVUOVoW=$w29`!9rk0bvJERc2&3PR=xZMm*Tr3SNjEs!k%v?;JU0f_p iOxzsZ+#JnaEzKRBEe-7yYzQlfo%}IEeslK}OGW^)C?JIZ delta 118 zcmX@In(4@DrVUOVoQ8&`Mg|6^24<7JJERc2&3PR=xZO+*4cv?k&7GVq4UAn}9nGDb iT`f&5EgcP9U5%W~-7M`CYzQlfo%}IEeslK}OGW^rMIciE diff --git a/docs/pages/Bloque3/reactI.html b/docs/pages/Bloque3/reactI.html index 1c0eafb..d8fe49e 100644 --- a/docs/pages/Bloque3/reactI.html +++ b/docs/pages/Bloque3/reactI.html @@ -6,8 +6,8 @@ - - + + diff --git a/docs/pages/Bloque3/t6.html b/docs/pages/Bloque3/t6.html index a227782..39b83ab 100644 --- a/docs/pages/Bloque3/t6.html +++ b/docs/pages/Bloque3/t6.html @@ -2,7 +2,7 @@ - + @@ -73,9 +73,9 @@ - - - + + + @@ -516,6 +516,29 @@ Proyecto Subsistema + + + + @@ -607,7 +630,7 @@

T6: Romancero Gitano I

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/pages/Bloque3/t6.pdf b/docs/pages/Bloque3/t6.pdf index aceecad4eba2b447a1e482cb82234468e140e9cd..95dd72b1c27a2eb00e6329a912acd077136298be 100644 GIT binary patch delta 133 zcmbO_nPuu^mJM@%>KGfC7+4ya8X9UF7^)i>sB0?d`{t*(B$lKqXt-Dz85o%vz?E!1 z`ICj$+05C*$j!jO&C=P@)y>Ss)!fL$+1$v?)yU1*+!QEar(i=!$#wyD##SZ(dix>p delta 133 zcmbO_nPuu^mJM@%>KGcD8W|Xv8k%Yw7^)i>sB0?d`{t*(B$lKqXt-Dz85o%vz?E!1 z`ICj$*~Hw^$->aW&C=P>(Z$5s&CJ-;#nQsf(8Soy%*oiv*iONQkdo~J?2N5U0CCVE A!T - + @@ -38,9 +38,9 @@ - - - + + + @@ -481,6 +481,29 @@ Proyecto Subsistema + + + + @@ -539,7 +562,7 @@

Rúbrica de evaluación

Fecha de última modificación
-

15 de enero de 2026

+

4 de marzo de 2026

diff --git a/docs/rubriuca.pdf b/docs/rubriuca.pdf index c52ce86583dbbfd3cad8fd3a6fe52a0d09bb20f2..4b88c587e2a770046962305a065c82c19a72a24e 100644 GIT binary patch delta 25870 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 delta 21079 zcmZs?Q;;r7w5?gTZQHi7%C>FW^_OkiTxHv~y~?(&-sg5doEy<^>4(h7oH4#RGQ1X~ zA{?ZC1s0eoxsa3$z{WC!E9S)(&yPu79l^GW*v88zew42BQKSnmM( zI&&v%E#=}ggk^B@iZ9GEPL!OfrA9DaQ94PI*)SGO)bZU}DK`kPhQ;|w-+CpyJFmNY zl==L=H1Cd(=gALmMdTz;X~6xm!Jqv+cMv>!DgU(81i{<8fJ zQxydUZobquhrBWV-)n7s4uBsBIOyb}Eq_uBdu`9ER>JJ(NWr()7sNgDG>Ma0+esLc zo}EJRs=6dJ(I<;pl_CA?ylTp_U6(yb(_A_3jQODc7+0)hbc9`U$F9ql&9V0Zij z=WOu%#f*iNsy+*ITx6D|lR6l7XLT~JsnXh4-dbiVdC(ud^bTQk{(U^VEcpm~le;bj zEJ#@1Pwy!a#tUjVE;YiUFh{XWlXK=Tr3kF`3e|sr6cp%~n)#xgF4-%e22@?QiE#Kq z?H=fiKQzoEY>ij~5$K-|DvKf$%Xw(Q#;9T} z_Fd$p-G4r-@{3UlSXcy+TZS}_ci%d*p={IQ4Xd0~w7D!=fBo$Zrp=qYLS~}TWW@?A zh?GSDK`5Tg9V9$hnHC24UtkNxBdkoUMa$fZ!W0}s;Sx=T& zJ~YYbJ7j;z`P&On!o)p~lOIy0+H-vcqh*IATufjrM_U3~PlddQh@C;L6c{}FotOn2 z$mHJ)&9$lyNcAxZwVVzW+86!=?>jgB*WV5paGI!~>{vj8V#$;A+A0Y7C)DgxJJc1}6mZ+(mv(R# zs^(P0RnE0_tbgQd$G_T76R4x$<2(@BqAY}A!W4!+Ef&C9U#CRJBD{RdQoTqHE-AwE&DEWwL0T)hQHD{IHj<=atNOcH%D1;TQZj!A zENzX9d(mH?t|ASMba73R>l&pKWJGog>O;6I!jGFDDT{m56#xWOl=aYW;u#=~MQxkb zTyMzY_N5`0&}oP$oANZB1n=9zE))m2``Znog-Aj!s|^(s)5H$Ny>bPwHyWxVx8H8CLsj42t?$e4Xm%qI%!^DMkLHD33%NEztDJwYU@+g^ba~fxW>p2 zYr<1R%58rVr~O0>H`5kDt&uKTM)9nO#kRB|t-Nd0n?-ObBWxa**^|Gd0p_7n^L!V~ zKyR{QgIgXS*+1DN5If#^;kGA7=zFExU_|R8y}IK-eq!u?Mpd3$Tf##}bfa+tVzDrL zr?+_)NB02w<1Fhez%=5v(tH5GRvdpy!Z(OWS3)7@9qk$fW=!AT{_;3za>WDRGz5A}yCO={DyrEjeZnu{?UqD`43nOc6u6Xg{61 zcnfLIoy#wuF!dd{NV{ml`-d;FGK(>VBLK zHtcS_nGCihAlH->?Y}Xb8-Yqqm<0l-v~1Rx;cnuaP_JPQ62!BBt&Ui(GcxkD%!Y1x$!Gl#E7EF@GUP2pOL`v=KyxOdY_IqZ;A*m zT&#eBd&GPNtf&0*mi0KtV_lj*yLmUay>I*F8-3vH6jo9O6Uqr#6SNCbc79by?pVqy)?2%UyU(DI{!ZfW|y5;p87$e`m7l4a5bHKC=c81+9P4hD} zJTD~{56LC4Va3^w5We;d!B))ooDd=YWKY*ySqlI&{Cn1F)@GSfNXg54-mq*(qVXyKaTSmfSHZvzKMQ5nJIjBrZSC!1sQy^k3)emz?Q6PybT2I;;- z^TF<#aWfjjs2^{dlepgm(n_bWxwnGd?_{00404+i0t|AN1Xp>T6S#Dz7_U6`;Wsmt z7Y*Qmlq%BdbO?b|S{oQ8!ARCeY_R&{xlErxotTMwh?`|^Yw7_iOGtg?Q<|EPO}fXd zMYD{9rnqU2Q*o|PYKdNyme&DVg>@vvwJ4jN?wrwD$SfE4(}=SkTW~Px;|wSbD>VcG zFRlOWjL``Czb%*SQ3RfVi)fRC8||YxHvrUfGTe@!P4mR@pEk0NXY%2;`IQPR)%33pdg#&Qk zeJBpOldsW+x{WqDaLndRo8#HRyQkn&(#Cl$L^}odr>U^guYL=AtuzS!9+!CZbPh&c z)5Uk)+i*4}bpqUh^B7DZ#J>;NX)yh!R7axsmc-_Ur(6W%3&JCRIiQ)`hB7sAM%K`}uSkG%Q{`iNc}ITZZGLS3W&siKHSOrAA@MHBCCB zV>tI}+Uz$LOA{`h?hG!ZHh?x2R|?Q3*K9GR;fBPMJ5)mTS6X;8x;ii~@->|I+aC0W z^x-IlB(rG0=bj-9VH}Yu_=7(-`ySMDR`KdHSw{cvRLpwG___7E3l2u=uZPX|MyK(? zx04924r1jh$9+xJmmc&o%&pESXgO8^vTOpEIbb!=AH ztSip0Q6n)c!uT85mKe(#M2WsnHDN9ftFm#lZP%R5M!Sn})`%!Bw=#fJWmbdfX^05~ z2yOj@+~9bdyGx-<&_X?r$Zb&T+{97Q-{Ih-jh2lUjir#0w{IPULJSW|JGggE$^f!| zbi?$D-otZ*)%LQ~=>R8|TZI?|-P<7`hI_`-+z}QUrsq_JwbA98#@^!^U5Cf#J+vBD zz2*x>-N;Veh~!cuT@I~^-<>VJubKVOTRK!DBmVIf4$BW7P`iC9? z-OA2OzT^8DdMfULB9J~9$@uo?4Ep?r`hUK@4{)OEjoGQGLR#fsTe;#@kKg^$MZ~6o zyI8BpR|UuT1z{@ZeyeHVTyQM47UBh*|$K>CyQRC7sqM${pG_B;hd7;mbgg=m& zt3FCFX7;B4pMv?XwqnE5>6D))jy8Dg(xvm^ko4ySel#nG^ zs*!~DVeOg(Y@xM<6oQg)XrnmYvV7K4$9Az|L2DaUr&!iS1TJ!h8^JCl|SA6rDv`bg&n`a z2XHABGCkt$(FM1Rak3tHyofqT7|)(QuroaL_XgpK>-)2rePc9dc*vvG1>nBcE2tu4 zjue<)#*icCt){V5%1GN-%AME-H%f^<couBVFSbw}E?~K85)}03 z8V3eP-{ywmV(BWg)59DgHMUBr(E<0gO_$i7po4bC!=v-xlIl))W2ZK6Tm-Hjr|(h@ zTiDIgw#T>YWDnpg{*~(g=djuTN6I$&;@bl!Q{$31Arb}vCu`u7Cy$V#033pZkVbBO zqxf5`V)_qi<=`TVN+?|y4 zF5H{9i$ak}aS{KvwNZ#40p6M04EQTHF1EwACy_hFoV~6u6a*(`E(K%zSKDc(v@R%! zpJXnS8!dKos>$aew<8Tru#PQ7)aQ#Q;2ZyP#(7S#1YwLNB1yqvL@kLWMNG0plZo1?%FvskQba%}fHuKGV4|di0V+iBu~rw7&SYy# zaU?Ik5Dk>552_#s-Q-Z)e`x1Xa8SJy95V}oq=hSpm`kBgSnh=rNoPVXi1|_x;Zao` z7cw$M^28)ylA)C997e>AgJ52lGeS?lz2X<#PWzVFKzZD4yv^Ufc=zkN+*BTW z#0TU$q%Te*e&)!iFG0_K`Y6b9?Nmp9x)rz=E8y!e@Q;2mS9c(s%$iqq@-8m9zFJwc z#0oTR5Yu1DIbD9jwv<3(cuE;BIaO43X4U#>B~m|UcAGKfh0s6VlM$SM2=VZsdrp3LusLPs?8V8*EsW!kFgn>P8KkPuTF2aUotl>?a^A!aMM7k zJr83v?~E-A)yLPFfQz+5J5A`zzYZgyND!X8mGYjvFyF1-}-oe^lU6oFVf`XBuEazjZgB4fgcl#jm%d7eyjdo9@iE0pM3GxN9XjB zy+ldqJ$=^GS`;zyD8CR>n@C)-mZ1B9c4nUF$n zf1>cZ=)_G{T8Ts&T4-&%Wb8IvvSMl#laZe10exA}{I){-Q`6CNocE8;29xeYKW$3g zL4nIPXb|4)I0#1waT&u3dCUxfpK={Hn7Ivp7wHV%uPyeCo$uQ9>og-IteH@xsc@A{L ztRxumcK&Ol6&um?X@hLIz-ANVw))ju*-Wo-13LTQ#>d!dC@+7zlQB ze&w324eZuF*SrJWjB;~wnqJ%HeqP!XJTsbDM-T7$Fc<+^)bVf;ID+=m(pDAP7zOq5 zvlfsIw?LdxrA%oj4JefEO!@c+F<~9|uN~a4Zw24MU>_EecL-tkEIW;YfQvEzGmel? zhdraV!k56??VTar943NQ+{DxK_b(Dc^1~LP#+2@xv74{iJ{j!-+BdBy#94Q^l%DBm2UORHdpc<}qSLDbnOdGyt`yrv?+X3q{5b5?5O&P6=-H7vCi3 z>Teg56Goj2Ui14R?#Hy+tkcpc4JnZ$7^!+ybR-59?{9?7bWoY&sBs|d(H;n+TVv7& zrFE=nSlsB?F$zPK`pR{-E72=bTa1&~cSDzk_jQpglPgqP=2kGBsG5Ft<0>WtTl`k! zN5B|Jy^w5FsG*T27e=JG33CQW^vD4-d|HH+7p-TDF9X;=8xW2G0yqo0{I&e@(`}a| zF6?(OgE7F-6)hH-A`EB5 zST@ty13PZw@TgnlES35`E!z2JO(tX$bvv{JD1G6Ks?6O-QtVOldp3r+I@$7as@n3^ zwBnF%48T{}Ue1>wU{DSJu0Kkyx z@kkLb+s9pd1XEld>P;K5<6Og%U9O`x!tre0vNmJuz@s|W;>mrpi4rB78%p>F3l*xc z@h~Y_&Uv3yQ*4liBbzF1!oJ4CBF8-c?#5l20{Gv9*5@^;_0Q9AMKJ~TD3PbBqAx0~ zYS&BaB&d7X8hiD{$kcvaim*UWZUB?EbOkGY`QzV-U^(VR>rRUKZWhI>9sDBm&M~HL zR)zI5y{{W)CM8uM=j3K0zwkhj+cN1gVuB8|nl1SFAymifo9Ki!b_DpU0#rF64Y4#J z7jk%yy;35L>`dq+mCEOxpt1zFu|J8H*jX_YBmgupL7~HaWv*l5l0w+)SpdV@rs3hY zIj(~TrLIr@oP0=+I5=+rgLr;sZFzT*fII^6n(RMB${}il=G^H%Q>blG$cshNVh%+**C)p?_3Mpozw09wLCFn)A6zoQW7pas z1F~+UBp1OIo$- z!d144xj^15M-^@@JQtcCpw4pQ^D2t-_-}EVz=ASfrq^q9Qsp8jOGR zQJ^mQPBIu#G6<58&>BLO?6T7vUl~mD#d? zkOC$Nw({^KV5$xXOzxd-dMI!i`>uPh@A{-ya*;gD@*=FpmL>KLyW;4K{InVnkq#3r z)T+N_n!hg2)cmL8U{$maPi2}w>pIZK?R*r_fmMR8GLe}@7OJU+qM>7;t2A?5C$9&Y zOAvPva#?eC4Vd*pJa%hPcgY!RkZ8~&Yd02xWN}rM{ukCBO12*YZZ})=PpmwP6&MNCC;S$ua?8>c zZ7pEANH>|AGMc7=Ex%JVuikF;Xn~x#Z14Gisa_Ua2mnqiYRr)=K&z0aP!PG%1aICn zAi|Nh`L_zyRtI%xkz+~hIA9`OLd4?iVF@vz{&N5yjCttqq37L^ngA|vd1S`xMyx0J z_(ob$(!VDVuNBDp{-nWqV>iO|r#|I_8uB!NAwHio9DpZiEYynxTK{l8R zRy9>!@gYrJkNbW5c#1Q-jh*)I*|wbAh8fv?D*)pNq$zOG+}tvG1Uhtr9Q?RL4J|90 zNvWCGxGP9nUTq?HTx!ort)`)H{SWH(X0Df-+vj-Qz$Xn3&+`*TOS2% zZ@+9V=1%CWAHK>Q+Tq&yFm;LWg49f2~0-R1PXC@tIrS+c**hdIuWggs& zA%LY8`;8=WN{D=aiD2$SlzYet|Js1Q^DTVAmgsLMFkKj>;yrG;qw5g)P(P+BXfA{3 zx!D2ER=?AXHu$<(!9L9wgQ2OMs@1`26#7vL{gg=C0>oQ!g6Ez0Hnm?S9SE!IDm0dF zAqHN_zVX*-mBl8bmU>-@;(?6|*v*{*BY?|I5tDG|dTw}+)s?ZINylD=-Ce=LF%M$S z(NjBkm!t1awLDjNWPQ7Rrenc*YahZCkDJ~mxVxOd;G3lyE_ z|7EoNdRIBb;uYz1*I{5Y?@=j+A54MQ-nH2kDc6?3!Y=|RCuK1r02T~F~`em2P>3yc^vExku z_nxFTiAPfx(&OL0;9=kXcyZ<+mf?KKg5-`1uy~^dxO$wbDp}ThquAM4K~CEG+^H572RuP?fp$1-*_Y_c}eepwcQ<&pKilL%AT)=xyW_I-n@4 zaUK)q>7?*Z2&55ZVSxp&b$)f02ML<=7#pVB2z8XUbfwgdf#)y6PZ_%ANOJL;fvi91 z{N5K*`V+6)sxe*mX`rsx82IVfZC5u_e64@Xzy3;a|3=n@?N1z}4hZ>m3%Z4f%@;&J zD~HLT|MT684V=r^+L~KcMBA_4Y0}~Y`TsC&a~;p^&R1AkAW zYGt4(g9dP~jzMdT_AF_66Qr8G_>(0pSioAyO z#B?=b!|3P60kAy-2IW zz!1W`C%ZmV5d9RQE>c&Nl%&m6Ra+W+dpkRKW@{Pg@Xjr1{-d!Q*3EyOXd`pg4i}w* zI!pRx2$ROm#wC{tpM99%I(4nK4ID}rg4XDc$!1TB08p{IH65IaogxHJ7&? z6oyPnJfgbJF`D`v+uG(^8-@ys?4YO2ju~wiLQF-rZ->)aYmr zreHErfMA7OR0D3edyKF7sIre^#q&Q2_QbHl?%eR4yxL7{!NlCLFgnx~@o=`eLL@&a zk-_D8PaWuTIxO*&22vGrTdC@p2g=wg^=?(3Hy_+8MdoINdZIO4r8b;w9cWm}fpM}R zRya6zgQ!AT1O2k&G}=nTbt7?J9Za_ zt;T=HULAq>cc?a@Rw+Z2r${(0D#k|=0hm!sRx?I-UYT#|Lx(=(;r%FKG_b&z9P5$5 zR>t{u@rSuayC+RkoyB5lDZX~bCvo^ZFn+%dgu;JN#(|9O{G&>#stWpL2X6DU zYLVRDP>_+L6+~T0ztDIji2P1e??k>(RGW5nJLm-!bkQtY*23J-66g-%$B6_0RRd(9^Gx*0EF??f zv8dA;75Wi79}FGm*4r!Y7vhY*fRMmX1C??@UhBkS)G#EUr(nf0ag{6p74hRR$HVJ%pf|VS}R~PG>tef9%0vn1+3!9kNs=cyYC&8HGmWnJ|wj(qra%tU`tB3NGGg#NY z*0>KXhknaoUc}iVawu{PjkUYc-ogL%@2O;EF`TZ1xk1;2;fh$~QlJ27Bu@B4xQme4 z4O>RzNDF;IP}8AaE)mNGxBLwGM+pcI?>0&%t{}D<92Pt+7&dPpfckQ+1Fs^EJ^p%G z+;P>rzyK_A<3trfQAJ*f1DYMSSu2jX3DiWxv-}E6r9FHoqxciZW+T0S(%y(~ zvX2bmN1!^UkW83($7tSyOl2qm_`XmrL91YH5@n4o_~94oGSL}HU2G_kpKruDuufax z7d5GUqVlWJGizcJ(3BQob0DMYbWtMN*E(;Ku05AmQ?{q;p0=kv<75JTKFa{fv6{Su zP)(cfhse;hoAV?cxgDe{xhw;Py(*XB(7*D@lb`6qY9t zghn4;&BdJFgy0Ty{bYJgV0hf(I>;xV@HS*qG{-7{*d_lBsQ1#A0_vEi9HmW&%gASb z6urNyzOQMjIRC60!6#Sv?s*`DJPVuJXtR$lzd@UUfNjoKEN-idc_Ix?-}0ZI--O-! z@p9rl8|M`t*g58WuroCYH}~Y$tB0A^ru$LD5Gksf&_CGo!7m8rx^B<#)|Y+fdXPl6 zWj%uzvYo#K2$P(Wp+QCFNqD^abyiu0{|$m!E}v?PY+EHu)lf^l;AxeoQN6Xk<} z2Kby0a*F=YnmMA%_ah!tfG<{DaO#cPw6*3oIC}k?s?sTa0r+@C_qcoU>U`$6wN2rL`>hAK?F^xx>p{k4) z1|8Y7j+Zk}o&UD1*|6m(Oll`gd(TeHZP-sUoTtrQ+~w1B@_#{*KroB{cRneZUl0=b ze^Q5J$t>s=+QpEcLpEXbmTg+DTUJYV zylqByURrlU^7CANg?u*iKA*VfTs-sWrcHl*cYpnFSrQd%Yg5EX5mY%y!|scRGau@QLEyYZ*wnL%_f^eH`{ye z6Zet5SC*+&^s~=={q+DX{SwcA#mo0M8)$|Kh*2M=4i4qOlYRBcE}-2Q^u`8G#&kJ=cs5%b7pSZmm3Q0SM& z&sU_?s?@2`FN|KO{UkbA8@u7Glt|H}$`>n%pFKOVQYx(8!n^_&M#B|$gawMT@s@sx zw@pvolGCc;ba^KL?}HUC}ZHH#k88OttEl zPfw8m_O*WGLzNeliGYDWCZkTQ+PKZueOuP-3IVTPOCQ_J(T(GXt}txL%^BW}&6wLn%L-}UP2w4mC@ z2>FP=F2Ov0qu)5aUv_U_Cxgh%7lIbu14LjXdCCh*dwbzI@ZtTe%M)Q2xALdqHBFkH z1Sie^@hmg|bYEp;+6;H>(Gy&gD93-Nn?liY*aLt*6_jSeNgy%6Jim13%$ybi>nvee z24Cx*XClmlpR8KReI!|qQw@i2klBd@tl3TG&(~k{NH=R(4z3NI&7z*7J zKgU|Sv9XF*SWsWoTQF}o6HbUF@5pou=nFIg!I*|=B?a0i_8jc2kzf?NuTM9U$gS>M zoCiz*$KUk}E!G%h>3wZ7bb$I7U6WQGVqYoY$w_pnBqQGmo zOTHhl9<|bli*YyCI+%^l)^FL`(^fLNLVJ*K6W{MVQhkCJM}0ZuZ3+v}(U3 zu8FZwywT-FeBWtz<8eG$!#-H&>K7YvF4c{8 zAQ3%7O6xmo`1?9TZ@IJ<)2dQluf*K%F$UZqVvse4(5&XB?hIh&_o#{X_bq#3pMG?n&-3=t>H4_V=j2$9t^8R~bMDW@~RQs`80EfHd8eI!%Jg zbG1?fv%v4MhvLdVj4nap>kQYspO%2FZP3Eg;|Qa*_@2(OGPc}Gi+aVOjMu%;#`QLQ zX{7tSK0y%T#rFKKd4hR_ z8BUASej&vKtI44!cUG$#6sy{Pgm*thuc0q_tPN^6(}5BWkLAxd01C0Q39{qKlEyW+j*@cM=JBjmQ7T%VCn@X3^3wtSkH zr0^n0tn`jFt%#Dctd2S;)^>M*kqq>GPFkRA{W2G4*6DQM#R8637m%sX9E<811zSq~ zWJbe0!bo=M->2^ir{aAbFCM;bn#kYGVM@DHJ<`nBj|P{;$eMYYIE%aaZAcN^`p6+i zeT{h))|%(>S6B<{Z8IkPX7j<_;1@)|Y=lT0CJJL_dAjfXo#IqvMjSdX-iusKrk?*6 zh3zgq;8WmDLk9Sx*0I=T#jUzr`X#z07eHv;(#vMp^gIQ4uB3*KJ4z)C?M?t~Q|9!6 z`x7u4LcD-^yioZbSs|i%guC~dR^S~fRtu;_BSPw|yQ z7glZ8*7+jR8tcn{?~`(Rc2$IHAxS|2SxS#t9($`ZN?*mEyWMVh?gmXlXEqgTLPR!dAc2OMpH(6@pAa5Qyw#?PP4zf-x8F^{FQySmvRmFWz80eCIy4D zdrA;|lK>i(d_!p(*)o*E%?vwf#g{lU@9z;wEvGEx>k~&Dqn22CmQ1K(mRAQ6E8Uc= z`qfQL;-ZYBkgF?GVFwN~4XP2kKYXj7fpj(VK{V~7IXQoXzvit%%~|tx93z<`&mINs z6hM$qw&Jt|9i|gDT9WS#p9jzQ`8Hz8e~npT`T^IUCmwUDmzWP+uO8n#mHNO#@|%0K z*%FZZzC1BwhlY4tqyiy6Fd3cLCwrDxoRgS7#>cO$`^Q-fPZMVT4MxIO82&EP-rG3# z04kbz=U%VUIrVn493Q?aq4s zaDeA(3mwEe33+8u#PhB#O1W}d5D|J`uqHTM7KFVg=?))0A`uARo(y_*IDC8{2#RP3 zNhqUIII}0*h5uXr87>y6$$W^`Y#3C4w~s~;*x!B?8hw)KJLEc62SOp@ud;wO6>}#Z zH~8%b{hfVQkve1r@*_*qj$<0g6sc9u4S=aFQKg79hhPuB_D4_JSy}$Flf0~QfY>t_ z#PM{XL2#*n28wFY?5f+qR8n&~G8Q$2_-K|plCH{Y&M)4gmSSQtiz+z=d_Pw0}@ zy*KZI`dfe6W_WE*0dLkDsuY5~;8>ZJ;2t+F$ZKfbi5=XhlVIc|O+tev)s)D&4&a+lmq zG$VY@KQdCEOe~yeL@Yd$Xu*(YD=;)Qa%hU1)%o&*oE^f81w^`DXbkaH@>ca>3ZzsT zDl81_6clM59t1nYu?OBqIJD~>4?rAZ@Lt^fCJUFK_Bl*7dTyYne}7eZ^3(nQT|5Uv|WgOh2`ob7A-b^m}k1}HO@WMetK zToClqEt$rh8aFi>hu#lIEdGU^u4qr1Ye~U4(%v>^G!S3;2b~e#A5AodeuW`pWJ-$7 zK##2wUS*O2qH`|3N{*3v9*{`p6x+}~PxZEhqf2#J^2i%?iD=ekrlVaAh9k&hZ(;3i z+P<|2?yuROoZ`}{ID6kn3gG7Uwc_S^Dn#+c?e%@-CphUBX&SMeXocg{N$8lEKn+7$%=m_I(t|to4E;#_oia{`HW6FM=Jpn zr(04Sd7DGFER6>~--Zn2UU44yVpX?a5f0NqODSmDSyvqvf_z=A0}z*gVkRu6D$<+& z1!2Fupy~?yY%d9XR8P6bdz6h{I`+vtM3YG61}zh!0b_OlXuN@DVABqsd}RG)c({A= zuyAKxhc7utRPc?lce{(m>M*f4C`jb`PZcjw1pv@rlAr&>wI)V%QJ~KBhJuZ zY5`?k#x-X-j!Gey1GuZHo|U(l2*$h5 zIizficX4ZLlpP7mm14f9{(&UNTGPHI*Kqe4ze}&!v z*2+CZ)xzkFOEBIeJ!JN#?OuU&d_rr3x}e|dL6RGUiChwS3Q&4){agOe52x+WqOn=k zR93}WMv0qowkVgy2GwDUOe3-%ofrH@roA+PxDqKA)=`)yZov6UDXLAB;V5m8!!U9X zofe}Q{B!whI)yxvxBVC53a|A{6ueRi=*6>R7%nzqv$}>R*s~HBm6i zNK$>3LgW!>Ff&URjd)L{ujz63ZDnX|i{SS{i}Sa?iQpS{ zZt|OS&R9<^j`+WiaV)F!%*-?lDNE!>sbR3yHihyYRDigxw3Mq;nUp8bl$bY}jmS>* z+Oh+oMQUfNo-%U-e2?1Zqv-HK#yl4jPFuOVw++wr*I&O=qjJ><{V1O8Oe8<)&4FM( zg2?dvO`xWmNrcnY^xm2jUO+Gojq^=iObL~B=c7hx8~VaW{$Cq2JI8+n zfrEyLNj@)usjkQ<6?P06f+PS1=(QGn;Qwbh*Z;5w04oRQ|7D_T(S+7jSRy|=%=07|^+RSdwPBiC%N z&Th&W#FW0?T^SjP5)PgN{=a@%3v(dg5k)Lf7pw+&*5s+_M)4Pr8|J|4Gl6B^T#v(j zC4=wOE6 zpoYL$(2Io^hdhrmJyMh`abVH0flv2}af4o7Her}Dg7n}x(h1t0!1#B(0?etAPvFn= zPh7er`2chhlT#6$EDEFgAL(IS58GEvhlHsV{dyrf`2>LEaH6!?KNbZA zGvknOK7m2joZRF+YW)0^JuAQ6Ao#k^cgDNzX7`@mmuG@Wv{Eiz0!D;ns^H=hXaWG( z%l)ta!`r$c^{D<*gVuVVA)^T_6XG$8OR_yi2 ziwW_6eyPwAW2X!hnL&VZy{IMx>^X-#YOTwDzCQh_gISZikQ8m=x+Z&0IfbRv{7jXmsc>IdME7;-6TaG(+fCT#!p zB>&#q&274Dy-c;Iu&|-#*-)=2jc1V?$n_``)=0*Rx>xSHSf8=!Gx?~$)eynNTR;6^Hf^ua>P<>Sm;qJKiYQaw^HkNZMB)jc(z~g|$I5fy+}x z$!Wy-Gak!zs9?t+m)C>7-aou7Z7lEwknXs$5LD+*fw}?9I@vaCXG|JgHjW`r9a zCA{JX8MOjL0_$1uD_kC6SXNY(F*X2}-i8ywrP@$)ju}ITXdx zdnEm24arh^$A%dmM=7vt&)YvhA?iPJ$TvE{Manaaf8>>oOM79wG^ zY?BB7>FR0e{uiW5Y1fpjTeOpDCuycu)cyQGVKf1wv%sj2w-o6rLxvIe1Qh;Q6JY?< zLHu!a@1oc_^RY-ozdgJ>o=n(82Bg84q@Jln(OgY%#9cyCH_1i}vr@n|ovGYR}%qWOjvFgyJzDKo^+JU~3M=z3! zEgtuuD-F?>q_!y!nD|k-5*$+)P2h+FoPk*RTij)P=(*2e;r9?ha*i^K}ZyZp&`Up_3IGn0KVOano z8l)bkJdbIPbiE2c0s;b0R430`0iEd_BYUtyEtz3nf_twtrO{&^J!0sGf4usOB)alO z!|T}IiZCxVueS}4hnNTOlK<_2;M487pW7X{m_I}at>gQ;p3>an8^dfc#Qwl&-3g(u zi-;eNjO~Kg9F>w3^!~|Cx@XUdGGPOJVZq2+!W``nFYA>1_)rv0|@K)Q(l7 zYP5*e8nt7_-ZZH48dX($l$P4ws;U{QC}MMZ&iQ}%pX;3KI^Un``F!8ceg7WB181w1 zcO)J|uTLWX(PyOdfu6hoYrfL2G}6M1STp%>+8iV1U3`kKDApyNQc~I`9jRmGJjMDr za=3V%Cw%`NKVKUARNL&tVPMw3_Wm&}$Ep-rrTYr^`c7#}hE_=EGU?{8+rLMc91ho- z@j+-u;!wahH?b*|KMq!N_*xz!b>swPT|T*jy>a_~?*XFek6hE5gMteLwpF@dq@kiR4CF>GiK_Ydt2 zyqbNltx1XP)|P}_vS%hguKASKXAd7hyL_cjmy4oiVP-(=QkAN|e1c zRwuwY9SMR*6J9ZI`^V0L+gB70DWhyiRxLh2MtIveW}AnVEPMh+7(=cofrH>CFF)j%?k}ahDf5$XAYCZPV&Y|$97Zv`v zUqD$lwAT56A^OtLC)}?IldGZ^b&_+dbnpWpC=Tf_C7tQVgmb#1mKRO*GAyMDUt?sE z*+z}3;2S>osz|HvRPiM=jC>v&wMZzhi{-G%^O%3=W;ZMYd6MEgN(OO@7-29H-pRfq zM|xByG`41MU@<1&J1ZGWiR)Mub(>w2kiRl*t4+6utcyL1_m-NA;mU@z6BE?{q(v6) zmPe|Mx_SAqC_qObtA63aqN>&kSrq3ze536$n|*v%l2i)OjHtrz44ehL7X7G-=bKaw zq)E!(mq|sLTU*T;8M-$!n_Jh}YWoyvjRF60IvanjkIBFt?LUHU09X259JL%{%yZW^ z-OohLxnGQ9#5UGyR3#WHvfV7Ev&<|!MB=z5Hr(&2i9FJ5P0c)ZW;{X$M#@E-tXxEQ zXG-+}rvnLv8fb$O5F_UN(S~O+HEP)8y`zv|v|a*5oD*)2?=>Oug1F z34Iqun51{@zc`g4Z(^m>s+>@Y>)cCkV7Qx@eA&}w+fF>oMo>}7(rn7FJAh{Sq=kd# zE;5PsCp%cExOrRRm`6Qde6G(j#ML#c`AEY;nBW}B}Of?1zuBP{#mHz;Ak(q=!kBg$oFWp4r(*e>t)|x znYj%zFL*IIcRXM%6uar@^aEETD~i_WuAn&lnjAPOgPpJaXo4QRFRxDq819fCSV50x zR8MGbhKNqz{S5>3-eMIZ@&gD_*9orAposI2Qdf(a3KPAmp-@#%XtJz*4AO3EC|> z9=5HU4;?X4oukYAtV$zDi_`M1p}Dum6VLW-se`QQ@@!poNpR|=I-zr)eS_N@OG|r8 zt(mpU#_2bGwA>&9W~FRYwq+RN_9! zITY-?*s!u+u7JBPKIsklB(liys%jQ+{YCiYrD0-ev0vZunG$9PT)e9~6QMV|w6r8k zj75J6POfN+x$=Q)J{eGfFvoyee4QI1?;;T}hse7oEpo!xPk3Oh{Oe^C%t(f_mHz~% z5}Nqfi6#ZKvkQ%)X{->D{xGeWvuIH?tK z?G5gT_!dMu%sFmTS|8e`<8qp1jqJkP;tdt%&PT|Js*vGT2yEC0{o(I_dP;j)$pH`i zkT!lb^=;aCac2E%LoGU%!=C?bP38XU-H^Jp%)h7Lo{t_aK^P2Ot)vE>dib*IvnVK- zcq1MucA<1hE{-T<|Bp4$KMq%^$-;S=^j|r>t?Rvi1@VnhX4C*V*dNC%h!szS2|{@x zy#L7p!{L%hK?Sl0p5}ZyfV^~TJHW&0(hmNf5Lh`E(}EKe~@j>mbRw+t-!Fc zH{&*=$lR|dgW?IIWFzXpEZT<1g<*KG_fMD$JVV(_{N{dDg%n$Z=`6WdrX@$s`={*} z)zjMDFl-^UcdnWKR#&;hLFWJhg<*Rd9(lg!P67{-?dlQ)X- z-=eR@>wHGUooPn`^mFxDEdTJn3Y|%DiuEmmd5cK!bOQ2j%RB2$ zGIaC2#cfSkIK#&0d_sPd);-o0S71>6%CYQ*mVfy74X%(?Iu*`+(^Kj%2g7v(W2^55 z2wsa#WTQwWOVl22pv~q8<2w*?@V2x1RrFe%$*1!sm^UGifnYeqZkv-iB!lWj$FfHz z!HhQ;c~TvJ)I1e>oh=kz*zXfy%3}cM8e2!cH@W<$NOGU);utjLoTd2c@cgk{T%1!@ zN886Fh;jlw(Ht-9y{{lCXrCIjV68o7(^Puu0?*%=GVj;nO1^lGIX+1b5F_kGdC8u* zz5OxOq^V6YA2tc@Kh4j{$k@-38T{7QCl|@2l_@d0|Cqt8V6WF_<=fBW&p|{tgui+xDtj08#z!R{!RgHms)EtaT$G0`lC!nWKj}206l^KX;D(w? zc!39Y8Fin{=7!TxbneELb9>c9>Hiib=%r2QU5F3G03{CCMy21seCz|FgR8n1IGC5G;w!Ho! zW&G<$x^MO!t?bARArZ3~!64vcpnls=`zR7xr$a?GKfw>`12MM{FLdz}Dh!|1*_u#Gx|_rW}n}Ey`Qv7NK@f3&?~4s)yy? z5djNc-x>1ww6k{ubkYr-N@u-bf8x0yp!}us64xQOP%w&j(mG zXlLKD-=8o|j6zZfd%}jcp=gA@$#h8jN*aJprI%ESlW?HzehLN&siX zz3;a$>7HTfTII(9{Jv}F!++als`H+C3y?(7#4`rSq9G9Php%Z*`BaqulCcCd zq;vq332teDCf!%OES?7Me(M-gsqtHv66v;Cn8nQKr;DtMmM?#KVnr7YNW&&6B#GyT zIe{q>U&7xhUT@A~o6aj$m^+@cAcC;hiGR8QdmG3Og+ja8O<9hljn6xslbkd5D;9o= zoCEX0id$Ut2gJm@3-SDb=SuPNN6>?o19cuqPLj_7&gevYnz#h?CY6+^VGj$9Vny?; zy;=-a&4Ra1AA&u`X4PWkIx`2m?g1=IiLwj%WOV7w zxQ4aJ9s3dH8_9<#P?uoooRG!=Cxc7HCK3g-Yv}X(bGB&0P8wpwjEMzSz{1A9ILo&h zgk~{g|6IXBD~sj&n~ic@r4U28KQqmuI*0-XKEdUKt}w*4lM!;J z69X}+Eq1+8yjAJU3@|nYk;TSzR=%b(@b zl_onNUl|{w#`sYI`3zxc`KR@t5)&qmn{&Iuhne4O&B%jI;358IdW=qjUo}1oB4^0= z(!fNW3lDjB`&qUhIbg|evkeN!``lsem-~LC;0}Idp=<-uoYrf}6CXc4BJ=e&4*kG~ z?z%Aa0j~D;A`n?9^Cl3x{xsMR9wc6E}v4|o25Ca^7;JTwqVOB*R(C@<6&>j2`!NGT}% zyXF!6qCgjE%+!DIeDu)m{Qe>QTV$3-m6`BdBm*dZfTp&GLZGyTBvZqa{29mMuy^>` z$JO=K_@TWGAi_~Vw}(ORR%aGf5o$RVFq{SzN$03Z1=nEd+|%xF@?DOLbQ9~>`0SR! z+{^sD;Xpo8pn&;b&Tm|KG15#`FDGV=LO48FA6(Uqu*;lSvrr^ka7PzdaP>A>Q1jc| ziyXGXCk*S{i$6o)Bm4F5y>QXMC#`ASOPV&u$4={w3", + "text": "Etiqueta <meta>\nLas etiquetas <meta> en HTML sirven para proporcionar metadatos sobre la página web. Estos metadatos no se muestran al usuario, pero son importantes para navegadores, buscadores, redes sociales y dispositivos.\n<head>\n <meta charset=\"UTF-8\"> <!-- Selecciona el conjunto de caracteres -->\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <!-- \"Hace la web Responsive\" -->\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>", "crumbs": [ "Bloque I Introducción", - "Semana 0", - "Preparación del entorno de trabajo" + "Semana 2", + "CSS" ] }, { - "objectID": "pages/Bloque1/entorno-reveal.html#ide", - "href": "pages/Bloque1/entorno-reveal.html#ide", - "title": "Preparación del entorno de trabajo", - "section": "IDE", - "text": "IDE\n¿Qué es una IDE?\nLas Integrated development environment (IDE) son aplicaciones diseñadas para facilitar la programación a los programadores.\nAunque no hay una lista de características propias de las IDE, suelen tener características comunes, por ejemplo:\n\nDebugger integrado en la interfaz\nGestor de archivos\nEditor de código inteligente: autocompletados" + "objectID": "pages/Bloque1/css.html#git-github", + "href": "pages/Bloque1/css.html#git-github", + "title": "CSS", + "section": "Git & GitHub:", + "text": "Git & GitHub:\nLos comandos de git nos permiten utilizar la cli para gestionar nuestro repositorio\ngit init # Incializa repositorio (= crear repo con GitHub)\ngit clone <url-repo> \n\ngit add <files> # Añade los archivos a la stagging area\ngit commit -m \"<mensaje de commit>\" # commit\n\ngit push # push\ngit pull # pull\n\ngit status # estado actual del repo\ngit log # historia reciente del log con poco detalle de profundidad\n\ngit diff <file> # muestra la diferencia entre la versión modificada ente un archivo y otro", + "crumbs": [ + "Bloque I Introducción", + "Semana 2", + "CSS" + ] }, { - "objectID": "pages/Bloque1/entorno-reveal.html#node.js-y-npm", - "href": "pages/Bloque1/entorno-reveal.html#node.js-y-npm", - "title": "Preparación del entorno de trabajo", - "section": "Node.JS y NPM", - "text": "Node.JS y NPM\n¿Qué es node JS?\nNode.js es un entorno de ejecución de JavaScript basado en el motor V8 de Google Chrome.\nPermite ejecutar código JavaScript directamente en el sistema operativo, sin depender de un navegador.\nDe este modo, el mismo lenguaje puede usarse tanto en el frontend como en el backend." + "objectID": "pages/Bloque1/css_p.html#problemas-de-html", + "href": "pages/Bloque1/css_p.html#problemas-de-html", + "title": "CSS", + "section": "Problemas de HTML", + "text": "Problemas de HTML\nHasta el momento hemos trabajado con HTML, que a pesar de ser muy práctico para la creación de la estructura interna de la web, presenta ciertas limitaciones a la hora de modificar el formato de la web, para ello se introduce CSS, una herramienta que nos va a permitir modificar el formato cómodamente." }, { - "objectID": "pages/Bloque1/entorno-reveal.html#git-y-github", - "href": "pages/Bloque1/entorno-reveal.html#git-y-github", - "title": "Preparación del entorno de trabajo", - "section": "Git y GitHub", - "text": "Git y GitHub\n¿Qué es Git?\nGit es un sistema de control de versiones distribuido. Permite registrar los cambios de un proyecto, volver a versiones anteriores y trabajar de forma colaborativa sin sobrescribir el trabajo de otros. Cada usuario dispone de una copia completa del repositorio, lo que facilita el trabajo sin conexión." + "objectID": "pages/Bloque1/css_p.html#formato-con-css", + "href": "pages/Bloque1/css_p.html#formato-con-css", + "title": "CSS", + "section": "Formato con CSS", + "text": "Formato con CSS\nAtributo style\nSupongamos que tenemos el siguiente elemento\n<p> Hola Mundo<p>. Por ahora el texto se mostrará en color negro, el color predeterminado de HTML para las etiquetas <p>\n\n\nHola mundo" }, { - "objectID": "pages/Bloque1/MAhtml2.html", - "href": "pages/Bloque1/MAhtml2.html", - "title": "MA: Mas HTML", + "objectID": "pages/Bloque1/css_p.html#etiqueta-meta", + "href": "pages/Bloque1/css_p.html#etiqueta-meta", + "title": "CSS", + "section": "Etiqueta ", + "text": "Etiqueta <meta>\nLas etiquetas <meta> en HTML sirven para proporcionar metadatos sobre la página web. Estos metadatos no se muestran al usuario, pero son importantes para navegadores, buscadores, redes sociales y dispositivos.\n<head>\n <meta charset=\"UTF-8\"> <!-- Selecciona el conjunto de caracteres -->\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <!-- \"Hace la web Responsive\" -->\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>" + }, + { + "objectID": "pages/Bloque1/css_p.html#git-github", + "href": "pages/Bloque1/css_p.html#git-github", + "title": "CSS", + "section": "Git & GitHub:", + "text": "Git & GitHub:\nLos comandos de git nos permiten utilizar la cli para gestionar nuestro repositorio\ngit init # Incializa repositorio (= crear repo con GitHub)\ngit clone <url-repo> \n\ngit add <files> # Añade los archivos a la stagging area\ngit commit -m \"<mensaje de commit>\" # commit\n\ngit push # push\ngit pull # pull\n\ngit status # estado actual del repo\ngit log # historia reciente del log con poco detalle de profundidad\n\ngit diff <file> # muestra la diferencia entre la versión modificada ente un archivo y otro" + }, + { + "objectID": "pages/Bloque1/MAcss.html", + "href": "pages/Bloque1/MAcss.html", + "title": "MA: Selectores y Pseudoselectores", "section": "", - "text": "Durante la explicación de teoría vista esta semana en clase nos hemos introducido en las etiquetas básicas de HTML.\nA continuación una selección de etiquetas que no hemos visto en clase, pero resulta interesante conocer, puesto que en determinadas ocasiones son útiles. Cada ítem de la lista es un enlace a la documentación de Mozilla donde está explicado el funcionamiento de la etiqueta de forma exhaustiva. No hay que conocer todos los aspectos de cada etiqueta, basta con tener una idea general de como funcionan.\n\ninput types. Muy importante conocer todos los tipos de inputs\ncode\niframe. Útil y ampliamente extendida\nhr. Línea horizontal\nfigure y figcaption. Permite insertar figura y pie de figura.\naudio. Insertar un audio en la página web.\nvideo. Insertar un audio en la página web.\nheader, main, footer. Son como <div> pero ya con usos por defecto preasignados.", + "text": "Además del id y las class, existen más selectores que son ampliamente utilizados en la programación web. El siguiente video los explica muy detallados y sirve como repaso para lo que se ha visto esta semana de CSS. El vídeo está en Inglés y dura 20 minutos.", "crumbs": [ "Bloque I Introducción", - "Semana 1", - "MA: Mas HTML" + "Semana 2", + "MA: Selectores y Pseudoselectores" ] }, { - "objectID": "pages/Bloque1/t1.html", - "href": "pages/Bloque1/t1.html", - "title": "T1: Web de HL I", + "objectID": "pages/Bloque1/t1a.html", + "href": "pages/Bloque1/t1a.html", + "title": "TA1: Mi CV I", "section": "", - "text": "La primera tarea de esta semana consiste en diseñar una página web para el equipo de generación espontánea llamado Hyperloop UPV, la web debe de ser realizada en un archivo HTML y debe de constar por lo menos de los siguientes apartados y estructura\n\nTítulo principal de la página <h1>\nVarios secciones cada una introducida por un título <h2> (si es necesario hacer <h3>)\n\nDescripción del equipo\nLista desordenada de los subsistemas\nLista de Partners por orden de importancia (UPV, )\nUn día en Hyperloop (nótese el título del apartado en cursiva)\n\nBreve descripción de lo que hacemos en el equipo, alguna foto\n\nMiembros\n\nUna tabla de miembros por subsistema (inventarse los datos)\n\nFormulario para solicitar unirse al equipo que solicite\n\nNombre\nApellido\nCurso (radius button)\nBotón de enviar\n\nLink a la web del TC de SW y a la oficial del equipo\n\nCada sección debe de estar contenido en un div de la siguiente forma\n\n<div>\n\n <h2>Títlo de sección</h2>\n\n <Contenido de la sección />\n\n</div>\nBase: Web", + "text": "A día de hoy es muy importante tener una imagen digital, por ello la tarea extra consite en crearte tu propia página web básica usando html.\nPuedes usar el CV de Antonio Machado como referencia.\nBase: Ejemplo", "crumbs": [ "Bloque I Introducción", "Semana 1", - "T1: Web de HL I" + "TA1: Mi CV I" ] }, { - "objectID": "pages/Bloque1/html.html", - "href": "pages/Bloque1/html.html", - "title": "HTML", + "objectID": "pages/Bloque1/bloque1.html", + "href": "pages/Bloque1/bloque1.html", + "title": "Bloque I Introducción", "section": "", - "text": "Contenido", + "text": "El objetivo del bloque 1 es sentar la base para la realización del curso, aprendiendo las competencias mínimas para realizar el curso.\nEn este bloque se hará una introducción: las herramientas de trabajo, el lenguaje de marcado HTML que permite crear páginas web estáticas y el lenguaje de programación de CSS que nos permite formatear webs previamente construidas.\nEste bloque se compone de 3 semanas, 2 tareas de clase y dos tareas voluntarias.", "crumbs": [ - "Bloque I Introducción", - "Semana 1", - "HTML" + "Bloque I Introducción" ] }, { - "objectID": "pages/Bloque1/html.html#estructura-básica-de-las-páginas-web", - "href": "pages/Bloque1/html.html#estructura-básica-de-las-páginas-web", - "title": "HTML", - "section": "Estructura básica de las páginas web", - "text": "Estructura básica de las páginas web\n\n¿Qué es una página web?\nUna página web es un documento digital accesible desde un navegador, compuesto por HTML, CSS y, cuando es necesario, JavaScript. Representa la unidad básica de contenido o interacción dentro de un sitio web y puede integrar tanto información estática como elementos dinámicos.\n\n\n¿Qué partes tiene una página web? (externas)", + "objectID": "pages/Bloque1/bloque1.html#contenido", + "href": "pages/Bloque1/bloque1.html#contenido", + "title": "Bloque I Introducción", + "section": "Contenido", + "text": "Contenido\n\n\n\n\n\n\n\n\n\n\n\n\nSemana\nFecha\nContenido\nContenido de la clase\nTarea Clase\nMaterial Extra\nTarea Extra\n\n\n\n\n0\n21/11/2025\nIntroducción\nPresentación TC, VSCode, Git, LiveShare y GitHub\n-\n-\n-\n\n\n1\n28/11/2025\nHTML\nEstructura básica, links, listas, tablas, form, img, div, span\nWeb HL I\nEtiquetas: HTML5, video, iframe\nMi porfolio I\n\n\n2\n05/12/2025\nCSS\nEstilos básicos, clases, id, archivos externos\nWeb HL II\nSelectores y Pseudoclases\nMi porfolio II", "crumbs": [ - "Bloque I Introducción", - "Semana 1", - "HTML" + "Bloque I Introducción" ] }, { - "objectID": "pages/Bloque1/html.html#html5", - "href": "pages/Bloque1/html.html#html5", - "title": "HTML", - "section": "HTML5", - "text": "HTML5\n\n¿Qué es HTML?\nHTML es un lenguaje de marcas que permite definir la estructura y el contenido de un documento para la web. Mediante un conjunto de etiquetas, el desarrollador describe elementos como textos, imágenes, enlaces o formularios, indicando su función dentro de la página. Es la base sobre la que posteriormente se aplican estilos (CSS) y comportamientos dinámicos (JavaScript).\n\n\nEstructura básica\n<!DOCTYPE html>\n<html>\n<head>\n\n</head>\n\n<body>\n\n <p>Clase 1 del TC</p>\n \n</body>\n</html>\nEn el código aparecen varias etiquetas HTML, y cada una tiene una etiqueta de apertura y una etiqueta de cierre (por ejemplo, <p> y </p>).\nEstas etiquetas delimitan y organizan el contenido del documento:\n- <head> agrupa la información del documento,\n- <body> contiene lo que verá el usuario,\n- <p> define un párrafo.\nLa función de las etiquetas es indicar al navegador qué es cada parte del documento y cómo debe interpretarla.\n\n\nHead\nSe corresponde con la cabecera de la pestaña, principalmente solo se modifica el logotipo y el contenido de esta.\nTambién se utiliza para almacenar los metadatos de la web, así como scripts de JavaScript y hojas de estilo de CSS.\n<!DOCTYPE html>\n<html>\n<head>\n\n <title> Web del TC </title>\n\n</head>\n\n<body>\n\n <p>Clase 1 del TC</p>\n \n</body>\n</html>\n\n\nBody\nSe corresponde con todo el contenido de la página dentro podemos utilizar multitud de etiquetas, acontinuación expondremos las más importantes.\nHasta el momento hemos trabajado únicamente con etiquietas invividuales, pero pronto veremos como podemos juntar varias etiquetas simples para obtener estructuras más complejas como tablas o formularios.\nTodo el código mostrado a partir de ahora se asume que esta correctamente ubicado dentro de una etiqueta body\n\n<p> Paragraph\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n<p>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n</p>\n\n\n<br> Break Line\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation\nullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n<p>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation\n <br></br>\n ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n</p>\n\n\n<ul> Unordered list\n\nFrancisco de Quevedo\nLope de Vega\nGóngora\n\n<ul>\n <li>Francisco de Quevedo</li>\n <li>Lope de Vega</li>\n <li>Góngora</li>\n</ul>\n\n\n<ol> Ordered list\n\nRecepción\nDiscurso del Rector\nDespedida\n\n<ol>\n <li>Recepción </li>\n <li>Discruso del Rector</li>\n <li>Despedida</li>\n</ol>\n\n\n<h#> Headings\n<h1>Título 1</h1>\n<h2>Título 2</h2>\n<h3>Título 3</h3>\n<h4>Título 4</h4>\n<h5>Título 5</h5>\n<h6>Título 6</h6>\n\n\n<div> Divisor y <span> Span\nEtiquetas contenedores, utilizadas para agrupar otras etiquetas, no presentan ningún efecto visible intrínsico, salvo que tras utilizar <div> se produce un salto de línea. Por lo que utilizaremos <div> para agrupar grandes grupos de etiquetas y <span> para fragementos más pequeños\n\n<div>\n<div>\n <h2>Capítulo 2 </h2>\n <p>\n Mio Cid Ruy Díaz por Burgos entró,<br></br>\n en su conpaña sessaenta pendones.<br></br>\n Exiénlo ver mugieres e varones,<br></br>\n burgeses e burgesas por las finiestras son,<br></br>\n plorando de los ojos, tanto avién el dolor,<br></br>\n de las sus bocas todos dizían una razón:<br></br>\n — ¡Dios, qué buen vassallo, si oviesse buen señor!—\n </p>\n</div>\n\n\n\n<strong> Strong, <i> Italic\nNegrita Itálica Negrita e Itálica\n<strong>Negrita</strong>\n<i>Itálica</i>\n<strong><i> Negrita e Itálica</i></strong>\n\n\nComentario\nEtiqueta invisible\n<p>Etiqueta invisible</p>\n\n<!-- Soy un comenario -->\n\n\nTablas\n\n\n\n\nProducto\n\n\nCantidad\n\n\nPrecio (€)\n\n\n\n\n\n\nManzanas\n\n\n10\n\n\n3,50\n\n\n\n\nNaranjas\n\n\n8\n\n\n4,00\n\n\n\n\nPlátanos\n\n\n6\n\n\n2,80\n\n\n\n\n\n\nTotal\n\n\n24\n\n\n10,30\n\n\n\n\n<table>\n <thead>\n <tr>\n <th>Producto</th>\n <th>Cantidad</th>\n <th>Precio (€)</th>\n </tr>\n </thead>\n\n <tbody>\n <tr>\n <td>Manzanas</td>\n <td>10</td>\n <td>3,50</td>\n </tr>\n <tr>\n <td>Naranjas</td>\n <td>8</td>\n <td>4,00</td>\n </tr>\n <tr>\n <td>Plátanos</td>\n <td>6</td>\n <td>2,80</td>\n </tr>\n </tbody>\n\n <tfoot>\n <tr>\n <td>Total</td>\n <td>24</td>\n <td>10,30</td>\n </tr>\n </tfoot>\n</table>\n\n\n<a> Link\nHyperloopUPV\n<!-- ¿Qué pasa con la URL -->\n<a>Hyperloop UPV</a>\n\nPropiedades HTML\nLas etiquetas o elementos html disponen de atributos que nos permiten modificar su comportamiento interno.\nEn el caso de las etiquetas <a> debemos de especificar en los atributos la referncia en cuestión\n <a href=\"https://hyperloopupv.com/\"> HyperloopUPV </a>\n\n\n\n<img> Image\n\n\n\n“Plaza de la Reina”\n\n\n<img src=\"../pr.jpg\" alt=\"Plaza con una fuente en el centro alrdedor casetas y fincas\">\n\n\n<form> Forms\nAmpliamente utilizados en HTML, trabajan sobre la etiqueta <input> la cual tiene muchos tipos.\n\n<input type=\"text\">\n\nNombre: \n\n<form>\n\n <label for=\"first-name\">Nombre:</label>\n\n <input type=\"text\" name=\"first-name\"/>\n</form>\n\n\n<input type=\"number\">\n\nEdad: \n\n<form>\n\n <label for=\"age\">Edad:</label>\n\n <input type=\"number\" name=\"age\" />\n</form>\n\n\n<input type=\"radio\">\n\nSubsistema: Software Firmware \n\n<form>\n\n <label for=\"sub\">Subsistema: </label><br />\n <input type=\"radio\" name=\"sub\" value=\"software\" /> Software <br />\n <input type=\"radio\" name=\"sub\" value=\"firmware\" /> Firmware <br />\n\n</form>\n\n\n<input type=\"submit\">\n\nNombre: \n\n\n<form>\n\n <label for=\"first-name\">Nombre:</label>\n <input type=\"text\" name=\"first-name\"/>\n\n <br/>\n\n <input type=\"submit\"/>\n</form>\n\n\n\n<button> Button\nPor ahora no los utilizaremos, pero es importante saber que existen\n\nSuscribirse\n\n<button>Suscribirse</button>", + "objectID": "pages/Bloque1/bloque1.html#material", + "href": "pages/Bloque1/bloque1.html#material", + "title": "Bloque I Introducción", + "section": "Material", + "text": "Material\n\nMDN (Mozilla Developer Network), HTML y CSS\nW3Schools HTML y CSS\nVisual Studio Code Manual VSCode\nCSS tricks CSS Avanzado", "crumbs": [ - "Bloque I Introducción", - "Semana 1", - "HTML" + "Bloque I Introducción" ] }, { - "objectID": "pages/Bloque1/html.html#primer-repo-de-git", - "href": "pages/Bloque1/html.html#primer-repo-de-git", - "title": "HTML", - "section": "Primer repo de Git", - "text": "Primer repo de Git\n\nIniciar sesión en cuenta de GitHub\nBarra superior derecha, Símbolo + > New Repo\nRepository Name\nDescription of the repo\nVisibility\nAdd README\nCrear repositorio\n\n\n\nDesde la ventana del repositorio creado\nCode <> > Clone > HTTPS > Copiar URL\nDesde VScode\nClonar repositorio (si no aparece F1, paleta de comandos Clonar Repositorio)\nPegar la URL del repo\nPresionar intro (equivalente a git clone)\n\n\n\nRealizar cambios\nDesde la barra derecha seleccionar menú de Git (3 nodos interconectados por dos aristas)\nAgregar presionando el + los archivos a la staging area (equivalente a git add <file>)\nEscribir mensaje de commit y presionar botón de confirmación (equivalente a git commit)\n\n\nUna vez se hayan realizados todos los commits deseados presionar la rueda de sincronización en la barra de estado. Este último cambio es equivalente a ejecutar git pull y git push.\npush sube los cambios al repositorio remoto pull actualiza los cambios de repositorio remoto por el local", + "objectID": "pages/Bloque1/t2a.html", + "href": "pages/Bloque1/t2a.html", + "title": "TA2: Mi CV II", + "section": "", + "text": "En la tarea previa definimos nuestra identidad digital, ahora es un buen momento dándole un toque personal con ayuda de CSS.\nSi no se realizó la T1A puede utilizar el CV de Antonio Machado como base sobre la que trabajar. (Click derecho guadrar enlace como)\nImportante: la hoja de estilos debe ser definida como un archivo externo.\nEl objetivo de esta tarea es evaluar, las habilidades de diseño y de investigación, por lo que no hay ningún ejemplo al que imitar. Siguiendo ese objetivo se le recomienda al alumno que investigue y descubrá el máximo número de propiedades CSS.", "crumbs": [ "Bloque I Introducción", - "Semana 1", - "HTML" + "Semana 2", + "TA2: Mi CV II" ] }, { @@ -584,444 +764,520 @@ "text": "Primer repo de Git\n\nIniciar sesión en cuenta de GitHub\nBarra superior derecha, Símbolo + > New Repo\nRepository Name\nDescription of the repo\nVisibility\nAdd README\nCrear repositorio" }, { - "objectID": "pages/Bloque1/t2a.html", - "href": "pages/Bloque1/t2a.html", - "title": "TA2: Mi CV II", + "objectID": "pages/Bloque1/html.html", + "href": "pages/Bloque1/html.html", + "title": "HTML", "section": "", - "text": "En la tarea previa definimos nuestra identidad digital, ahora es un buen momento dándole un toque personal con ayuda de CSS.\nSi no se realizó la T1A puede utilizar el CV de Antonio Machado como base sobre la que trabajar. (Click derecho guadrar enlace como)\nImportante: la hoja de estilos debe ser definida como un archivo externo.\nEl objetivo de esta tarea es evaluar, las habilidades de diseño y de investigación, por lo que no hay ningún ejemplo al que imitar. Siguiendo ese objetivo se le recomienda al alumno que investigue y descubrá el máximo número de propiedades CSS.", + "text": "Contenido", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "TA2: Mi CV II" + "Semana 1", + "HTML" ] }, { - "objectID": "pages/Bloque1/bloque1.html", - "href": "pages/Bloque1/bloque1.html", - "title": "Bloque I Introducción", - "section": "", - "text": "El objetivo del bloque 1 es sentar la base para la realización del curso, aprendiendo las competencias mínimas para realizar el curso.\nEn este bloque se hará una introducción: las herramientas de trabajo, el lenguaje de marcado HTML que permite crear páginas web estáticas y el lenguaje de programación de CSS que nos permite formatear webs previamente construidas.\nEste bloque se compone de 3 semanas, 2 tareas de clase y dos tareas voluntarias.", + "objectID": "pages/Bloque1/html.html#estructura-básica-de-las-páginas-web", + "href": "pages/Bloque1/html.html#estructura-básica-de-las-páginas-web", + "title": "HTML", + "section": "Estructura básica de las páginas web", + "text": "Estructura básica de las páginas web\n\n¿Qué es una página web?\nUna página web es un documento digital accesible desde un navegador, compuesto por HTML, CSS y, cuando es necesario, JavaScript. Representa la unidad básica de contenido o interacción dentro de un sitio web y puede integrar tanto información estática como elementos dinámicos.\n\n\n¿Qué partes tiene una página web? (externas)", "crumbs": [ - "Bloque I Introducción" + "Bloque I Introducción", + "Semana 1", + "HTML" ] }, { - "objectID": "pages/Bloque1/bloque1.html#contenido", - "href": "pages/Bloque1/bloque1.html#contenido", - "title": "Bloque I Introducción", - "section": "Contenido", - "text": "Contenido\n\n\n\n\n\n\n\n\n\n\n\n\nSemana\nFecha\nContenido\nContenido de la clase\nTarea Clase\nMaterial Extra\nTarea Extra\n\n\n\n\n0\n21/11/2025\nIntroducción\nPresentación TC, VSCode, Git, LiveShare y GitHub\n-\n-\n-\n\n\n1\n28/11/2025\nHTML\nEstructura básica, links, listas, tablas, form, img, div, span\nWeb HL I\nEtiquetas: HTML5, video, iframe\nMi porfolio I\n\n\n2\n05/12/2025\nCSS\nEstilos básicos, clases, id, archivos externos\nWeb HL II\nSelectores y Pseudoclases\nMi porfolio II", + "objectID": "pages/Bloque1/html.html#html5", + "href": "pages/Bloque1/html.html#html5", + "title": "HTML", + "section": "HTML5", + "text": "HTML5\n\n¿Qué es HTML?\nHTML es un lenguaje de marcas que permite definir la estructura y el contenido de un documento para la web. Mediante un conjunto de etiquetas, el desarrollador describe elementos como textos, imágenes, enlaces o formularios, indicando su función dentro de la página. Es la base sobre la que posteriormente se aplican estilos (CSS) y comportamientos dinámicos (JavaScript).\n\n\nEstructura básica\n<!DOCTYPE html>\n<html>\n<head>\n\n</head>\n\n<body>\n\n <p>Clase 1 del TC</p>\n \n</body>\n</html>\nEn el código aparecen varias etiquetas HTML, y cada una tiene una etiqueta de apertura y una etiqueta de cierre (por ejemplo, <p> y </p>).\nEstas etiquetas delimitan y organizan el contenido del documento:\n- <head> agrupa la información del documento,\n- <body> contiene lo que verá el usuario,\n- <p> define un párrafo.\nLa función de las etiquetas es indicar al navegador qué es cada parte del documento y cómo debe interpretarla.\n\n\nHead\nSe corresponde con la cabecera de la pestaña, principalmente solo se modifica el logotipo y el contenido de esta.\nTambién se utiliza para almacenar los metadatos de la web, así como scripts de JavaScript y hojas de estilo de CSS.\n<!DOCTYPE html>\n<html>\n<head>\n\n <title> Web del TC </title>\n\n</head>\n\n<body>\n\n <p>Clase 1 del TC</p>\n \n</body>\n</html>\n\n\nBody\nSe corresponde con todo el contenido de la página dentro podemos utilizar multitud de etiquetas, acontinuación expondremos las más importantes.\nHasta el momento hemos trabajado únicamente con etiquietas invividuales, pero pronto veremos como podemos juntar varias etiquetas simples para obtener estructuras más complejas como tablas o formularios.\nTodo el código mostrado a partir de ahora se asume que esta correctamente ubicado dentro de una etiqueta body\n\n<p> Paragraph\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n<p>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n</p>\n\n\n<br> Break Line\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation\nullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n<p>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation\n <br></br>\n ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n</p>\n\n\n<ul> Unordered list\n\nFrancisco de Quevedo\nLope de Vega\nGóngora\n\n<ul>\n <li>Francisco de Quevedo</li>\n <li>Lope de Vega</li>\n <li>Góngora</li>\n</ul>\n\n\n<ol> Ordered list\n\nRecepción\nDiscurso del Rector\nDespedida\n\n<ol>\n <li>Recepción </li>\n <li>Discruso del Rector</li>\n <li>Despedida</li>\n</ol>\n\n\n<h#> Headings\n<h1>Título 1</h1>\n<h2>Título 2</h2>\n<h3>Título 3</h3>\n<h4>Título 4</h4>\n<h5>Título 5</h5>\n<h6>Título 6</h6>\n\n\n<div> Divisor y <span> Span\nEtiquetas contenedores, utilizadas para agrupar otras etiquetas, no presentan ningún efecto visible intrínsico, salvo que tras utilizar <div> se produce un salto de línea. Por lo que utilizaremos <div> para agrupar grandes grupos de etiquetas y <span> para fragementos más pequeños\n\n<div>\n<div>\n <h2>Capítulo 2 </h2>\n <p>\n Mio Cid Ruy Díaz por Burgos entró,<br></br>\n en su conpaña sessaenta pendones.<br></br>\n Exiénlo ver mugieres e varones,<br></br>\n burgeses e burgesas por las finiestras son,<br></br>\n plorando de los ojos, tanto avién el dolor,<br></br>\n de las sus bocas todos dizían una razón:<br></br>\n — ¡Dios, qué buen vassallo, si oviesse buen señor!—\n </p>\n</div>\n\n\n\n<strong> Strong, <i> Italic\nNegrita Itálica Negrita e Itálica\n<strong>Negrita</strong>\n<i>Itálica</i>\n<strong><i> Negrita e Itálica</i></strong>\n\n\nComentario\nEtiqueta invisible\n<p>Etiqueta invisible</p>\n\n<!-- Soy un comenario -->\n\n\nTablas\n\n\n\n\nProducto\n\n\nCantidad\n\n\nPrecio (€)\n\n\n\n\n\n\nManzanas\n\n\n10\n\n\n3,50\n\n\n\n\nNaranjas\n\n\n8\n\n\n4,00\n\n\n\n\nPlátanos\n\n\n6\n\n\n2,80\n\n\n\n\n\n\nTotal\n\n\n24\n\n\n10,30\n\n\n\n\n<table>\n <thead>\n <tr>\n <th>Producto</th>\n <th>Cantidad</th>\n <th>Precio (€)</th>\n </tr>\n </thead>\n\n <tbody>\n <tr>\n <td>Manzanas</td>\n <td>10</td>\n <td>3,50</td>\n </tr>\n <tr>\n <td>Naranjas</td>\n <td>8</td>\n <td>4,00</td>\n </tr>\n <tr>\n <td>Plátanos</td>\n <td>6</td>\n <td>2,80</td>\n </tr>\n </tbody>\n\n <tfoot>\n <tr>\n <td>Total</td>\n <td>24</td>\n <td>10,30</td>\n </tr>\n </tfoot>\n</table>\n\n\n<a> Link\nHyperloopUPV\n<!-- ¿Qué pasa con la URL -->\n<a>Hyperloop UPV</a>\n\nPropiedades HTML\nLas etiquetas o elementos html disponen de atributos que nos permiten modificar su comportamiento interno.\nEn el caso de las etiquetas <a> debemos de especificar en los atributos la referncia en cuestión\n <a href=\"https://hyperloopupv.com/\"> HyperloopUPV </a>\n\n\n\n<img> Image\n\n\n\n“Plaza de la Reina”\n\n\n<img src=\"../pr.jpg\" alt=\"Plaza con una fuente en el centro alrdedor casetas y fincas\">\n\n\n<form> Forms\nAmpliamente utilizados en HTML, trabajan sobre la etiqueta <input> la cual tiene muchos tipos.\n\n<input type=\"text\">\n\nNombre: \n\n<form>\n\n <label for=\"first-name\">Nombre:</label>\n\n <input type=\"text\" name=\"first-name\"/>\n</form>\n\n\n<input type=\"number\">\n\nEdad: \n\n<form>\n\n <label for=\"age\">Edad:</label>\n\n <input type=\"number\" name=\"age\" />\n</form>\n\n\n<input type=\"radio\">\n\nSubsistema: Software Firmware \n\n<form>\n\n <label for=\"sub\">Subsistema: </label><br />\n <input type=\"radio\" name=\"sub\" value=\"software\" /> Software <br />\n <input type=\"radio\" name=\"sub\" value=\"firmware\" /> Firmware <br />\n\n</form>\n\n\n<input type=\"submit\">\n\nNombre: \n\n\n<form>\n\n <label for=\"first-name\">Nombre:</label>\n <input type=\"text\" name=\"first-name\"/>\n\n <br/>\n\n <input type=\"submit\"/>\n</form>\n\n\n\n<button> Button\nPor ahora no los utilizaremos, pero es importante saber que existen\n\nSuscribirse\n\n<button>Suscribirse</button>", "crumbs": [ - "Bloque I Introducción" + "Bloque I Introducción", + "Semana 1", + "HTML" ] }, { - "objectID": "pages/Bloque1/bloque1.html#material", - "href": "pages/Bloque1/bloque1.html#material", - "title": "Bloque I Introducción", - "section": "Material", - "text": "Material\n\nMDN (Mozilla Developer Network), HTML y CSS\nW3Schools HTML y CSS\nVisual Studio Code Manual VSCode\nCSS tricks CSS Avanzado", + "objectID": "pages/Bloque1/html.html#primer-repo-de-git", + "href": "pages/Bloque1/html.html#primer-repo-de-git", + "title": "HTML", + "section": "Primer repo de Git", + "text": "Primer repo de Git\n\nIniciar sesión en cuenta de GitHub\nBarra superior derecha, Símbolo + > New Repo\nRepository Name\nDescription of the repo\nVisibility\nAdd README\nCrear repositorio\n\n\n\nDesde la ventana del repositorio creado\nCode <> > Clone > HTTPS > Copiar URL\nDesde VScode\nClonar repositorio (si no aparece F1, paleta de comandos Clonar Repositorio)\nPegar la URL del repo\nPresionar intro (equivalente a git clone)\n\n\n\nRealizar cambios\nDesde la barra derecha seleccionar menú de Git (3 nodos interconectados por dos aristas)\nAgregar presionando el + los archivos a la staging area (equivalente a git add <file>)\nEscribir mensaje de commit y presionar botón de confirmación (equivalente a git commit)\n\n\nUna vez se hayan realizados todos los commits deseados presionar la rueda de sincronización en la barra de estado. Este último cambio es equivalente a ejecutar git pull y git push.\npush sube los cambios al repositorio remoto pull actualiza los cambios de repositorio remoto por el local", "crumbs": [ - "Bloque I Introducción" + "Bloque I Introducción", + "Semana 1", + "HTML" ] }, { - "objectID": "pages/Bloque1/t1a.html", - "href": "pages/Bloque1/t1a.html", - "title": "TA1: Mi CV I", + "objectID": "pages/Bloque1/t1.html", + "href": "pages/Bloque1/t1.html", + "title": "T1: Web de HL I", "section": "", - "text": "A día de hoy es muy importante tener una imagen digital, por ello la tarea extra consite en crearte tu propia página web básica usando html.\nPuedes usar el CV de Antonio Machado como referencia.\nBase: Ejemplo", + "text": "La primera tarea de esta semana consiste en diseñar una página web para el equipo de generación espontánea llamado Hyperloop UPV, la web debe de ser realizada en un archivo HTML y debe de constar por lo menos de los siguientes apartados y estructura\n\nTítulo principal de la página <h1>\nVarios secciones cada una introducida por un título <h2> (si es necesario hacer <h3>)\n\nDescripción del equipo\nLista desordenada de los subsistemas\nLista de Partners por orden de importancia (UPV, )\nUn día en Hyperloop (nótese el título del apartado en cursiva)\n\nBreve descripción de lo que hacemos en el equipo, alguna foto\n\nMiembros\n\nUna tabla de miembros por subsistema (inventarse los datos)\n\nFormulario para solicitar unirse al equipo que solicite\n\nNombre\nApellido\nCurso (radius button)\nBotón de enviar\n\nLink a la web del TC de SW y a la oficial del equipo\n\nCada sección debe de estar contenido en un div de la siguiente forma\n\n<div>\n\n <h2>Títlo de sección</h2>\n\n <Contenido de la sección />\n\n</div>\nBase: Web", "crumbs": [ "Bloque I Introducción", "Semana 1", - "TA1: Mi CV I" + "T1: Web de HL I" ] }, { - "objectID": "pages/Bloque1/MAcss.html", - "href": "pages/Bloque1/MAcss.html", - "title": "MA: Selectores y Pseudoselectores", + "objectID": "pages/Bloque1/MAhtml2.html", + "href": "pages/Bloque1/MAhtml2.html", + "title": "MA: Mas HTML", "section": "", - "text": "Además del id y las class, existen más selectores que son ampliamente utilizados en la programación web. El siguiente video los explica muy detallados y sirve como repaso para lo que se ha visto esta semana de CSS. El vídeo está en Inglés y dura 20 minutos.", + "text": "Durante la explicación de teoría vista esta semana en clase nos hemos introducido en las etiquetas básicas de HTML.\nA continuación una selección de etiquetas que no hemos visto en clase, pero resulta interesante conocer, puesto que en determinadas ocasiones son útiles. Cada ítem de la lista es un enlace a la documentación de Mozilla donde está explicado el funcionamiento de la etiqueta de forma exhaustiva. No hay que conocer todos los aspectos de cada etiqueta, basta con tener una idea general de como funcionan.\n\ninput types. Muy importante conocer todos los tipos de inputs\ncode\niframe. Útil y ampliamente extendida\nhr. Línea horizontal\nfigure y figcaption. Permite insertar figura y pie de figura.\naudio. Insertar un audio en la página web.\nvideo. Insertar un audio en la página web.\nheader, main, footer. Son como <div> pero ya con usos por defecto preasignados.", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "MA: Selectores y Pseudoselectores" + "Semana 1", + "MA: Mas HTML" ] }, { - "objectID": "pages/Bloque1/css_p.html#problemas-de-html", - "href": "pages/Bloque1/css_p.html#problemas-de-html", - "title": "CSS", - "section": "Problemas de HTML", - "text": "Problemas de HTML\nHasta el momento hemos trabajado con HTML, que a pesar de ser muy práctico para la creación de la estructura interna de la web, presenta ciertas limitaciones a la hora de modificar el formato de la web, para ello se introduce CSS, una herramienta que nos va a permitir modificar el formato cómodamente." + "objectID": "pages/Bloque1/entorno-reveal.html#ide", + "href": "pages/Bloque1/entorno-reveal.html#ide", + "title": "Preparación del entorno de trabajo", + "section": "IDE", + "text": "IDE\n¿Qué es una IDE?\nLas Integrated development environment (IDE) son aplicaciones diseñadas para facilitar la programación a los programadores.\nAunque no hay una lista de características propias de las IDE, suelen tener características comunes, por ejemplo:\n\nDebugger integrado en la interfaz\nGestor de archivos\nEditor de código inteligente: autocompletados" }, { - "objectID": "pages/Bloque1/css_p.html#formato-con-css", - "href": "pages/Bloque1/css_p.html#formato-con-css", - "title": "CSS", - "section": "Formato con CSS", - "text": "Formato con CSS\nAtributo style\nSupongamos que tenemos el siguiente elemento\n<p> Hola Mundo<p>. Por ahora el texto se mostrará en color negro, el color predeterminado de HTML para las etiquetas <p>\n\n\nHola mundo" + "objectID": "pages/Bloque1/entorno-reveal.html#node.js-y-npm", + "href": "pages/Bloque1/entorno-reveal.html#node.js-y-npm", + "title": "Preparación del entorno de trabajo", + "section": "Node.JS y NPM", + "text": "Node.JS y NPM\n¿Qué es node JS?\nNode.js es un entorno de ejecución de JavaScript basado en el motor V8 de Google Chrome.\nPermite ejecutar código JavaScript directamente en el sistema operativo, sin depender de un navegador.\nDe este modo, el mismo lenguaje puede usarse tanto en el frontend como en el backend." }, { - "objectID": "pages/Bloque1/css_p.html#etiqueta-meta", - "href": "pages/Bloque1/css_p.html#etiqueta-meta", - "title": "CSS", - "section": "Etiqueta ", - "text": "Etiqueta <meta>\nLas etiquetas <meta> en HTML sirven para proporcionar metadatos sobre la página web. Estos metadatos no se muestran al usuario, pero son importantes para navegadores, buscadores, redes sociales y dispositivos.\n<head>\n <meta charset=\"UTF-8\"> <!-- Selecciona el conjunto de caracteres -->\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <!-- \"Hace la web Responsive\" -->\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>" + "objectID": "pages/Bloque1/entorno-reveal.html#git-y-github", + "href": "pages/Bloque1/entorno-reveal.html#git-y-github", + "title": "Preparación del entorno de trabajo", + "section": "Git y GitHub", + "text": "Git y GitHub\n¿Qué es Git?\nGit es un sistema de control de versiones distribuido. Permite registrar los cambios de un proyecto, volver a versiones anteriores y trabajar de forma colaborativa sin sobrescribir el trabajo de otros. Cada usuario dispone de una copia completa del repositorio, lo que facilita el trabajo sin conexión." }, { - "objectID": "pages/Bloque1/css_p.html#git-github", - "href": "pages/Bloque1/css_p.html#git-github", - "title": "CSS", - "section": "Git & GitHub:", - "text": "Git & GitHub:\nLos comandos de git nos permiten utilizar la cli para gestionar nuestro repositorio\ngit init # Incializa repositorio (= crear repo con GitHub)\ngit clone <url-repo> \n\ngit add <files> # Añade los archivos a la stagging area\ngit commit -m \"<mensaje de commit>\" # commit\n\ngit push # push\ngit pull # pull\n\ngit status # estado actual del repo\ngit log # historia reciente del log con poco detalle de profundidad\n\ngit diff <file> # muestra la diferencia entre la versión modificada ente un archivo y otro" - }, - { - "objectID": "pages/Bloque1/css.html", - "href": "pages/Bloque1/css.html", - "title": "CSS", + "objectID": "pages/Bloque1/entorno.html", + "href": "pages/Bloque1/entorno.html", + "title": "Preparación del entorno de trabajo", "section": "", "text": "Contenido", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "CSS" + "Semana 0", + "Preparación del entorno de trabajo" ] }, { - "objectID": "pages/Bloque1/css.html#problemas-de-html", - "href": "pages/Bloque1/css.html#problemas-de-html", - "title": "CSS", - "section": "Problemas de HTML", - "text": "Problemas de HTML\nHasta el momento hemos trabajado con HTML, que a pesar de ser muy práctico para la creación de la estructura interna de la web, presenta ciertas limitaciones a la hora de modificar el formato de la web, para ello se introduce CSS, una herramienta que nos va a permitir modificar el formato cómodamente.", + "objectID": "pages/Bloque1/entorno.html#ide", + "href": "pages/Bloque1/entorno.html#ide", + "title": "Preparación del entorno de trabajo", + "section": "IDE", + "text": "IDE\n\n¿Qué es una IDE?\nLas Integrated development environment (IDE) son aplicaciones diseñadas para facilitar la programación a los programadores.\nAunque no hay una lista de características propias de las IDE, suelen tener características comunes, por ejemplo:\n\nDebugger integrado en la interfaz\nGestor de archivos\nEditor de código inteligente: autocompletados\n\n\n\n¿Cuántas IDE existen?\n\nAndroid Studio\nRStudio\nEclipse\n\n\n\n¿Qué IDE utilizaremos nosotros?\nPrincipalmente trabajaremos con VSCode una IDE de proposito general que configuraremos para el desarrollo frontend\n\nInstalación de VScode\n\nEnlace\n\n\nFamiliarizarse con VSCode\n\nBarra lateral:\n\nExplorador de archivos\nMenú de Git\nMenú de extensiones\nBuscar\nDebugger\n\nEditor o área de edición: componente más importante de la IDE, lugar donde se escribe el código.\n\n\n\nExtensiones\nLas extensiones son aplicaciones software desarolladas por empresas o por particulares para modificar o agregar una nueva funcionalidad a las IDE. Pueden ir desde pequeñas modificaciones del tema o de la UI, o incorporar nuevas funcionalidades como la interacción con bases de datos.\n\nLiveServer\nNosotros para el transcurso del curso utilizaremos la extensión Liveserver que nos permitirá desplegar comodamente un pequeño servidor para la programación con HTML (Ahondaremos más la próxima semana)\n\nInstalación de LiveServer\n\n\nEntrar en el menú de extensiones\nBuscar por liveserver\nSeleccionar extensión\nInstalar\n\n\nAl concluir la instalación debería de aparecer en la parte derecha de la barra de estado (barra interior)", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "CSS" + "Semana 0", + "Preparación del entorno de trabajo" ] }, { - "objectID": "pages/Bloque1/css.html#formato-con-css", - "href": "pages/Bloque1/css.html#formato-con-css", - "title": "CSS", - "section": "Formato con CSS", - "text": "Formato con CSS\n\nAtributo style\nSupongamos que tenemos el siguiente elemento\n<p> Hola Mundo<p>. Por ahora el texto se mostrará en color negro, el color predeterminado de HTML para las etiquetas <p>\n\n\nHola mundo\n\n\nSi se desea modificar el formato intrínseco de esta etiqueta <p> debemos incluir la propiedad style que, como su nombre indica nos permitirá modificar su estilo. Dentro de este atributo se ha de insertar propiedad CSS (no confundir con los atributos html). La propiedad CSS especifica que aspecto visual del contenido de la etiqueta. Por ejemplo, si se desea modificar el color de la letra se debe de utilizar la propiedad color (nótese que no lleva u).\n<p style=\"color:red\">Hola Mundo</p>\n\n<!-- Equivalente en Hexadecimal -->\n\n<p style=\"color:#ff0000\">Hola Mundo</p>\n\n\nHola Mundo\n\n\nSí deseamos modificar más de una propiedad CSS deberemos de serparalas dentro de la etiqueta con un punto y coma\n<p style=\"color:#ff0000; font-size: 44px\">Hola Mundo</p>\n\n\nHola Mundo\n\n\n\nProblemas del atributo style\nEl atributo style resulta útil para formatear una etiqueta individualmente, pero resulta tedioso y repetitivo para más de una etiqueta. Observe el siguiente ejemplo\n<p>Autores del culteranismo marcados en rojo<p>\n\n<ul>\n <li>Francisco de Quevedo</li>\n <li style=\"color:red; text-decoration: underline; font-size:30px;\">Luis de Góngora</li>\n <li>Baltasar Gracián</li>\n <li style=\"color:red; text-decoration: underline; font-size:30px;\">Pedro Soto de Rojas</li>\n <li>Tirso de Molina</li>\n <li>Calderón de la Barca</li>\n</ul>\n\n\nAutores del culteranismo marcados en rojo\n\n\n\nFrancisco de Quevedo\n\n\nLuis de Góngora\n\n\nBaltasar Gracián\n\n\nPedro Soto de Rojas\n\n\nTirso de Molina\n\n\nCalderón de la Barca\n\n\n\nProblemas:\n\nRepetición de mucho código\nAlta posibilidad error\nPoca escalabilidad\n\nSi añadimos por ejempo a Luis Carrillo y Sotomayor (autor culteranista) hay que volver a repetir todo el atributo\nSi deseasemos cambiar el color de rojo a verde deberemos modificar cada uno de los atributos\n\n\n\n\n\nClases e ID\n\nClases\nLa solución a este problema son las clases que nos permiten identificar aquellos componentes con características de formato similares. Se agregan como atributos a cada etiqueta\n<p>Autores del culteranismo marcados en rojo<p> <!--En este caso no se marcan en rojo-->\n\n<ul>\n <li>Francisco de Quevedo</li>\n <li class=\"culteranista\">Luis de Góngora</li>\n <li>Baltasar Gracián</li>\n <li class=\"culteranista\">Pedro Soto de Rojas</li>\n <li>Tirso de Molina</li>\n <li>Calderón de la Barca</li>\n</ul>\n\nEtiqueta <style>\nAhora para marcar en rojo los culterantistas se ha de indicar el formato de todos en la class culteranista, para ello nos definiremos una hoja de estilo que será común para todo el documento. La hoja de estilos se define en el <head> de la siguiente forma:\n<head>\n<!-- Fragemento HTML -->\n<style>\n /*Fragmento CSS*/\n .culteranistas{ /*Nótese el punto*/\n color: red;\n text-size: 40px;\n background-color: blue;\n text-decoration: underline; /*Este último ';' no es obligatorio como tal, pero es recomendable, en HTML3 y CSS2 daba error si se incluía*/\n }\n</style> \n<!--Fin de la etiqueta Style, seguimos con html-->\n</head>\nAhora se visualizará correctamente, además se añadirá el fondo azul\n\n\nComposición de clases\nSuponga que tenemos dos clases, una primera clase que modifica el tipo de letra a monospace que aplicaremos a los autores culteranistas y una segunda que modifica el grosor de la letra que se aplicará sobre los autores de lírica.\n<head><style>\n .culteranista {\n font-family: monospace;\n }\n .lirica {\n font-weight: bold;\n }\n .autores {\n list-style: square;\n }\n</style></head>\n\n<body>\n <ul class=\"autores\">\n <li class=\"lirica\">Fray Luis de León</li>\n <li class=\"culteranista\">Hortensio Félix de Paravicino</li>\n <li class=\"culteranista lirica\">Lope de Vega</li>\n <li class=\"lirica\">San Juan de la Cruz</li>\n </ul>\n</body>\n\n\n\nFray Luis de León\n\n\nHortensio Félix de Paravicino\n\n\nLope de Vega\n\n\nSan Juan de la Cruz\n\n\n\n\n\n\nID\nLos ID son como las clases pero solo se pueden utlizar una vez por sitio web. Es útil para cosas que no se deben repetir más de una vez por sitio web.\n<style>\n#principal{\n text-align: center\n color:blue\n}\n</style>\n<!--[...]-->\n<div id=\"principal\">\n <h4>Teatro Romántico></h4>\n <p>El retablo romántico se caracteriza por exaltar la libertad creadora,\n la expresión intensa de los sentimientos individuales, el gusto por lo\n misterioso y lo sublime, y la reivindicación de la imaginación frente a\n las reglas clásicas.</p>\n</div>\n\n\nTeatro Romántico\n\n\nEl retablo romántico se caracteriza por exaltar la libertad creadora, la expresión intensa de los sentimientos individuales, el gusto por lo misterioso y lo sublime, y la reivindicación de la imaginación frente a las reglas clásicas.\n\n\n\n\n\nPropiedades CSS\n\nborder y border-radius\nLa propiedad border es una propiedad abreviada (shorthand) que en realidad combina tres propiedades más pequeñas:\n\nborder-width → grosor del borde\n\nborder-style → estilo del borde (solid, dashed, dotted, etc.)\n\nborder-color → color del borde\n\nPor ejemplo, estas dos definiciones son equivalentes:\n/* Forma abreviada */\n.caja {\n border: 2px solid red;\n}\n\n/* Forma “desdoblada” en 3 mini propiedades */\n.caja-desdoblada {\n border-width: 2px;\n border-style: solid;\n border-color: red;\n}\n Lope de Vega\n\n\nborder-top, border-right, border-bottom, border-left\nCSS permite aplicar bordes distintos en cada lado. Cada uno funciona igual que border pero aplicado a un solo lado:\nborder-top\nborder-right\nborder-bottom\nborder-left\n.caja-bordes {\n border-top: 3px solid red;\n border-right: 2px dashed blue;\n border-bottom: 4px dotted green;\n border-left: 5px double orange;\n}\nTambién pueden desdoblarse:\n.caja-top-desdoblado {\n border-top-width: 4px;\n border-top-style: solid;\n border-top-color: purple;\n}\n\n\nmargin y padding\nLas propiedades margin y padding controlan el espacio alrededor de los elementos, pero cada una actúa en una zona distinta:\n\nmargin → espacio externo, fuera del borde del elemento\n\npadding → espacio interno, entre el contenido y el borde\n\nVisualmente:\n\n\n \n\n\n\n CONTENT\n\n\n\n\n<div style=\"background:#f0f0f0; padding:20px;\">\n <!-- MARGIN (gris claro alrededor del borde) -->\n <!-- BORDER -->\n <div style=\"border:3px solid black\">\n <!-- PADDING (espacio interno) -->\n <div style=\"background:#d0ffd0; padding:15px;\">\n <!-- CONTENT -->\n <span style=\"background-color:white\">CONTENT</span>\n </div>\n </div>\n</div>\n\nRegla Trouble\nCuando margin o padding usan 4 valores, el orden siempre es el mismo:\ntop, right, bottom, left\nPara recordarlo fácilmente se utiliza la regla mnemotécnica Trouble:\n\nT → Top (arriba)\n\nR → Right (derecha)\n\nB → Bottom (abajo)\n\nL → Left (izquierda)\n\nEs decir:\nmargin: top right bottom left;\npadding: top right bottom left;\n\n\n\n\n\n\nTipTruco para los ingenieros: La regla de la mano derecha\n\n\n\nEl orden de los margin y de los padding siempre es en sentido horario.\nPor lo que podemos utilizar la regla de la mano derecha de la inducción electro magnética asumiendo que el vector intensidad apunta hacia la pantalla\n\n\n\n\n\n\nArchivos externos CSS\nIncluir en la cabecerá el CSS presenta ventajas como tener la página web en un único archivo. Sin embargo en la práctica normalmente trabajaremos con más de 2 archivos por lo que incluir uno más o uno menos no marca la diferencia. Por lo que podemos separar el css en un archivo externo .css. De esta forma podremos reutilizar las hojas de estilos.\n<head>\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>", + "objectID": "pages/Bloque1/entorno.html#node.js-y-npm", + "href": "pages/Bloque1/entorno.html#node.js-y-npm", + "title": "Preparación del entorno de trabajo", + "section": "Node.JS y NPM", + "text": "Node.JS y NPM\n\n¿Qué es node JS?\nNode.js es un entorno de ejecución de JavaScript basado en el motor V8 de Google Chrome.\nPermite ejecutar código JavaScript directamente en el sistema operativo, sin depender de un navegador.\nDe este modo, el mismo lenguaje puede usarse tanto en el frontend como en el backend.\n\n\n¿Qué es NPM?\nNPM (Node Package Manager) es el gestor de paquetes de Node.js.\nFacilita la instalación, actualización y gestión de librerías que amplían las funcionalidades de los proyectos.\nDescarga node y npm nodejs.org", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "CSS" + "Semana 0", + "Preparación del entorno de trabajo" ] }, { - "objectID": "pages/Bloque1/css.html#etiqueta-meta", - "href": "pages/Bloque1/css.html#etiqueta-meta", - "title": "CSS", - "section": "Etiqueta ", - "text": "Etiqueta <meta>\nLas etiquetas <meta> en HTML sirven para proporcionar metadatos sobre la página web. Estos metadatos no se muestran al usuario, pero son importantes para navegadores, buscadores, redes sociales y dispositivos.\n<head>\n <meta charset=\"UTF-8\"> <!-- Selecciona el conjunto de caracteres -->\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <!-- \"Hace la web Responsive\" -->\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>", + "objectID": "pages/Bloque1/entorno.html#git-y-github", + "href": "pages/Bloque1/entorno.html#git-y-github", + "title": "Preparación del entorno de trabajo", + "section": "Git y GitHub", + "text": "Git y GitHub\n\n¿Qué es Git?\nGit es un sistema de control de versiones distribuido. Permite registrar los cambios de un proyecto, volver a versiones anteriores y trabajar de forma colaborativa sin sobrescribir el trabajo de otros. Cada usuario dispone de una copia completa del repositorio, lo que facilita el trabajo sin conexión.\n\n\n¿Qué es GitHub?\nGitHub es una plataforma en la nube que utiliza Git para almacenar y gestionar proyectos. Permite compartir código, colaborar con otros desarrolladores y mantener un control de versiones centralizado.\n\n\nGit frente GitHub\n\nGit es la herramienta de control de versiones.(Software Libre, Linux Fundation)\nGitHub es la plataforma online donde se alojan los repositorios y se facilita el trabajo en equipo. (Coporativa Microsoft)\n\n\n\nUso de Git y GitHub\nEn Hyperloop UPV, tanto en los subsistemas de Software y Firmware utilizamos GitHub como herramienta de gestión de código.\nNosotros en el TC, también trataremos de facilitarnos con esta herramienta\n\n\nInstalación de Git y Cuenta de GitHub\n\nInstalación de Git\nCuenta de GitHub\n\n\n\nDiagrama de trabajo de Git\n\n\nGit en VScode", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "CSS" + "Semana 0", + "Preparación del entorno de trabajo" ] }, { - "objectID": "pages/Bloque1/css.html#git-github", - "href": "pages/Bloque1/css.html#git-github", - "title": "CSS", - "section": "Git & GitHub:", - "text": "Git & GitHub:\nLos comandos de git nos permiten utilizar la cli para gestionar nuestro repositorio\ngit init # Incializa repositorio (= crear repo con GitHub)\ngit clone <url-repo> \n\ngit add <files> # Añade los archivos a la stagging area\ngit commit -m \"<mensaje de commit>\" # commit\n\ngit push # push\ngit pull # pull\n\ngit status # estado actual del repo\ngit log # historia reciente del log con poco detalle de profundidad\n\ngit diff <file> # muestra la diferencia entre la versión modificada ente un archivo y otro", + "objectID": "pages/rubric.html", + "href": "pages/rubric.html", + "title": "Rúbrica de evaluación", + "section": "", + "text": "Durante el curso seguiremos la siguiente rúbrica para la calificación de las tareas. A pesar de que las calificaciones no son importantes, la rúbrica es un buen recordatorio de que aspectos hay que tener en cuenta en la programación web.\n\n\n\nPuntuación\n\n\nNo aplica\n\n\nDeficiente(0–4)\n\n\nInsuficiente(4–5)\n\n\nAceptable(5–7)\n\n\nBueno(7–9)\n\n\nExcelente(9–10)\n\n\n\n\nDiseño\n\n\nNo aplica.\n\n\nDiseño desordenado y/o con problemas de visualización funcional.\n\n\nDiseño básico pero con problemas de visualización o estructura.\n\n\nDiseño claro y ordenado, cumple los requisitos básicos.\n\n\nDiseño cuidado, buena estética y estructura clara.\n\n\nDiseño profesional, limpio, pulido y sobresaliente.\n\n\n\n\nProgramación\n\n\nNo aplica.\n\n\nCódigo incompleto o con errores graves.\n\n\nCódigo funcional parcialmente y/o con errores importantes.\n\n\nCódigo funcional y adecuado a la tarea.\n\n\nCódigo bien estructurado con mejoras respecto a lo exigido.\n\n\nCódigo impecable, eficiente y muy bien organizado.\n\n\n\n\nEsfuerzo e implicación\n\n\nNo aplica.\n\n\nBajo esfuerzo o dedicación mínima.\n\n\nEsfuerzo adecuado pero limitado.\n\n\nEsfuerzo notable, cumple con lo requerido.\n\n\nEsfuerzo claro, trabajo más allá de lo solicitado.\n\n\nDedicación sobresaliente y trabajo excepcional.\n\n\n\n\nDocumentación / Claridad\n\n\nNo aplica.\n\n\nDocumentación mínima o inexistente.\n\n\nDocumentación incompleta o confusa.\n\n\nDocumentación clara y suficiente.\n\n\nDocumentación bien presentada y detallada.\n\n\nDocumentación excelente y altamente profesional.\n\n\n\n\nFuncionalidad\n\n\nNo aplica.\n\n\nNo funciona o no cumple objetivos.\n\n\nFunciona de forma parcial.\n\n\nFunciona correctamente.\n\n\nFunciona con mejoras o funcionalidades extra.\n\n\nFunciona perfectamente y supera expectativas.\n\n\n\n\nInnovación\n\n\n(Nota extra)\n\n\n\n\nTOTAL:\n\n\n\n\n/60\n\n\n\n\nObservaciones:\n\n\n\n\n\nLa nota total será sobre 60 si hay algun criterio que no se aplique, se modificará la nota para que esté sobre base 60.", "crumbs": [ - "Bloque I Introducción", - "Semana 2", - "CSS" + "Rúbrica de evaluación" ] }, { - "objectID": "pages/Bloque1/t2.html", - "href": "pages/Bloque1/t2.html", - "title": "T2: Web de HL II", + "objectID": "pages/Bloque2/ti.html", + "href": "pages/Bloque2/ti.html", + "title": "TI: Ejercicios JS", "section": "", - "text": "El objetivo de esta tarea, es poner en práctica lo aprendido en clase para ello vamos a formatear la web de nuestro equipo de Hyperloop, (tarea de la semana pasada).\nSe debe formatear para que quede como está Web, cuanto más se parezca mejor.\nNotas:\nLa hoja de estilos debe de estar incluida en el la etiqueta <style> del <head>.\nPara conseguir que los bordes de la table, td, tr… colapsen (que solo haya un borde y no dos) se debe utilizar la propiedad border-collapse.\nSi no se realizó la T1, puede utilizar este archivo html como base (click derechao guardar enlace como).", + "text": "El objetivo de estos ejercicios es repasar aquellas funcionalidades de JavaScript que difieren del resto de lenguajes de programación empirica, por lo que los siguentes ejercicios de DEBEN DE RESOLVER SIN UTILIZAR NINGUNA CONDICIONAL NI NINGÚN BUCLE.\nPrincipalmente trabajarás con:\nDebe de realizar la tarea enun archivo js, para comprobar el resultado debe de ejecutar desde la terminal con node nombreArchivo.js.", "crumbs": [ - "Bloque I Introducción", - "Semana 2", - "T2: Web de HL II" + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" ] }, { - "objectID": "pages/Bloque2/jsI-reveal.html#introducción-a-js", - "href": "pages/Bloque2/jsI-reveal.html#introducción-a-js", - "title": "Introducción a JS", - "section": "Introducción a JS", - "text": "Introducción a JS\n¿Qué es JavaScript?\n\nEs el lenguaje de programación del navegador.\nCreado en 1995 por Brendan Eich\nPermite crear comportamientos dinámicos: responder a clics, validar formularios, mostrar u ocultar elementos, generar contenido nuevo, etc.\nSe ejecuta directamente en el navegador, sin necesidad de instalación.\nJunto con HTML y CSS forma el trinomio esencial del desarrollo web\n\nLa siguiente tabla recuerda las difrencias entre HTML, CSS y JS:" + "objectID": "pages/Bloque2/ti.html#ejercicio-1", + "href": "pages/Bloque2/ti.html#ejercicio-1", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 1", + "text": "Ejercicio 1\nDefina un array llamado arrOriginal con el siguiente contenido numérico. Este array será el origen de datos para los ejercicios posteriores, salvo que se indique lo contrario.\n3, 4, 2, 4, 4, 5, 12, 24, 3, 23, 232, 2, -3, -9, 2, -23, 200, -23, 12, 43, 4, -32, -32, 0, 23, 23", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] }, { - "objectID": "pages/Bloque2/jsI-reveal.html#programación-en-js", - "href": "pages/Bloque2/jsI-reveal.html#programación-en-js", - "title": "Introducción a JS", - "section": "Programación en JS", - "text": "Programación en JS\nCaracterísticas generales de JS\n\nTipado dinámico\n\nTipado débil Coerción Implicita\n\nMultiparadigma\n\nÁmbito léxico (estático)\n\nModelo basado en prototipos (polimorfismo de inclusión por composición)\n\nFunciones de primera clase\n\nFunciones de orden superior" + "objectID": "pages/Bloque2/ti.html#ejercicio-2", + "href": "pages/Bloque2/ti.html#ejercicio-2", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 2", + "text": "Ejercicio 2\nPartiendo del array arrOriginal, imprima por pantalla la siguiente frase:\n\n\"En el subsistema de software somos x miembros\"\n\ndonde x debe tomar, sucesivamente, cada uno de los valores de arrOriginal.\nImprima por pantalla el resultado.\n\nSalida esperada (ejemplo):\n\nEn el subsistema de software somos 3 miembros\nEn el subsistema de software somos 4 miembros\nEn el subsistema de software somos 2 miembros", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] }, { - "objectID": "pages/Bloque2/jsI.html", - "href": "pages/Bloque2/jsI.html", - "title": "Introducción a JS", - "section": "", - "text": "Contenido" + "objectID": "pages/Bloque2/ti.html#ejercicio-3", + "href": "pages/Bloque2/ti.html#ejercicio-3", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 3", + "text": "Ejercicio 3\nPartiendo de arrOriginal, cree un nuevo array llamado arrPositivos que contenga únicamente números positivos.\nUtilice arrPositivos para imprimir por pantalla las frases correspondientes.", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] }, { - "objectID": "pages/Bloque2/jsI.html#introducción-a-js", - "href": "pages/Bloque2/jsI.html#introducción-a-js", - "title": "Introducción a JS", - "section": "Introducción a JS", - "text": "Introducción a JS\n\n¿Qué es JavaScript?\n\nEs el lenguaje de programación del navegador.\nCreado en 1995 por Brendan Eich\nPermite crear comportamientos dinámicos: responder a clics, validar formularios, mostrar u ocultar elementos, generar contenido nuevo, etc.\nSe ejecuta directamente en el navegador, sin necesidad de instalación.\nJunto con HTML y CSS forma el trinomio esencial del desarrollo web\n\nLa siguiente tabla recuerda las difrencias entre HTML, CSS y JS:\n\n\n\nCapa\nLenguaje\nFunción principal\n\n\n\n\nContenido\nHTML\nEstructura del documento\n\n\nPresentación\nCSS\nApariencia y diseño\n\n\nComportamiento\nJavaScript\nInteractividad y lógica" + "objectID": "pages/Bloque2/ti.html#ejercicio-4", + "href": "pages/Bloque2/ti.html#ejercicio-4", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 4", + "text": "Ejercicio 4\nPartiendo de arrPositivos, cree un nuevo array llamado arrValidos que cumpla además el siguiente criterio:\n\nEl número máximo de personas es 10\n\nImprima por pantalla las frases correspondientes a arrValidos.", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] }, { - "objectID": "pages/Bloque2/jsI.html#programación-en-js", - "href": "pages/Bloque2/jsI.html#programación-en-js", - "title": "Introducción a JS", - "section": "Programación en JS", - "text": "Programación en JS\n\nCaracterísticas generales de JS\n\nTipado dinámico\n\nTipado débil Coerción Implicita\n\nMultiparadigma\n\nÁmbito léxico (estático)\n\nModelo basado en prototipos (polimorfismo de inclusión por composición)\n\nFunciones de primera clase\n\nFunciones de orden superior\n\n\nClosures / Copia viva\nReflexión (Reflect, Proxy, descriptores)\n\nMetaprogramación\nSin Polimorfismo Ad-hoc de sobrecarga, ni Polimorfismo universal genérico\n\n\nEjecución single-threaded\n\nAsincronía no bloqueante\n\nPromises / async–await\n\nGarbage collection\nInteroperabilidad con JSON\n\n\n\nTipos\n\nPrimitivos\n\nstring — cadenas de texto\n\nnumber — números (enteros y decimales)\nboolean — verdadero o falso\n\nnull — ausencia intencional de valor\n\nundefined — valor no inicializado\n\nsymbol\nbigint\n\n\n\nTipos de referencia\n\nObject\n\nArray\n\nFunc tion\n\nMap / Set\n\nDate\n\n\n\n\nCaracterísticas del sistema de tipos\n\nTipado dinámico\n\nTipado débil\n\nLos primitivos se copian por valor\n\nLos objetos se copian por referencia\n\n\n\nVariables\n\nlet\n\nTipado: dinámico\nAlcance: estático\nMutables\nHoisting\nNo globales\nShadowing permitido\n\n\n\nconst\nNo son verdaderamente constantes\n\nTipado: dinámico\nAlcance: estático\nInmutables en la referencia (no permiten reasignación)\nHoisting\nNo globales\nShadowing permitido\n\n\n\nvar\nNo se usa\n\nTipado: dinámico\nAlcance: de función (no de bloque)\nMutables\nHoisting (inicializadas como undefined)\nGlobales si se declaran en el ámbito global (propiedad de window/globalThis)\nShadowing permitido, pero con reglas inconsistentes (puede causar illegal shadowing en combinación con let/const)" + "objectID": "pages/Bloque2/ti.html#ejercicio-5", + "href": "pages/Bloque2/ti.html#ejercicio-5", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 5", + "text": "Ejercicio 5\nPartiendo nuevamente de arrOriginal, cree un nuevo array llamado arrFiltrado que contenga únicamente aquellos elementos que cumplan todas las siguientes condiciones:\n\nSean positivos\n\nSean pares\n\nSean menores que 100", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] }, { - "objectID": "pages/Bloque2/tia.html", - "href": "pages/Bloque2/tia.html", - "title": "TAI: La objetización de las personas", - "section": "", - "text": "El objetivo de esta tarea es aplicar los conocimientos básicos de programación orientada a objetos en JavaScript, haciendo uso de las clases definidas en ES6. En particular, se evaluará el uso de:\n\nherencia entre clases\nencapsulación mediante propiedades privadas\ngetters y setters usando las palabras clave get y set\nmétodos estáticos\nvalidación de datos\n\nPara ello se definirá una jerarquía de clases que represente un equipo de Hyperloop.", + "objectID": "pages/Bloque2/ti.html#ejercicio-6", + "href": "pages/Bloque2/ti.html#ejercicio-6", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 6", + "text": "Ejercicio 6\nPartiendo de arrFiltrado:\n\nCree un nuevo array llamado arrCubos elevando al cubo cada uno de sus elementos\n\nA partir de arrCubos, cree un nuevo array llamado arrCubosFiltrados que contenga únicamente aquellos valores cuyo resultado termine en 0.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TAI: La objetización de las personas" + "TI: Ejercicios JS" ] }, { - "objectID": "pages/Bloque2/tia.html#objetivo-de-la-tarea", - "href": "pages/Bloque2/tia.html#objetivo-de-la-tarea", - "title": "TAI: La objetización de las personas", + "objectID": "pages/Bloque2/ti.html#ejercicio-7", + "href": "pages/Bloque2/ti.html#ejercicio-7", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 7", + "text": "Ejercicio 7\nPartiendo de arrCubosFiltrados, cree un nuevo array llamado arrFinal añadiendo el valor 21.", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] + }, + { + "objectID": "pages/Bloque2/ti.html#ejercicio-8", + "href": "pages/Bloque2/ti.html#ejercicio-8", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 8", + "text": "Ejercicio 8\nPartiendo de arrFinal, cree un nuevo array independiente llamado arrCopia, de forma que cualquier modificación posterior no afecte a arrFinal.", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] + }, + { + "objectID": "pages/Bloque2/intensivo.html", + "href": "pages/Bloque2/intensivo.html", + "title": "Repaso Intensivo JS", "section": "", - "text": "El objetivo de esta tarea es aplicar los conocimientos básicos de programación orientada a objetos en JavaScript, haciendo uso de las clases definidas en ES6. En particular, se evaluará el uso de:\n\nherencia entre clases\nencapsulación mediante propiedades privadas\ngetters y setters usando las palabras clave get y set\nmétodos estáticos\nvalidación de datos\n\nPara ello se definirá una jerarquía de clases que represente un equipo de Hyperloop.", + "text": "Contenido\nRepaso intensivo de JavaScript, tiene como objetivo dar una introducción del lenguaje, a usuarios que ya tengan experiencia previa programando.\nDescargar archivo de código (click derecho guardar enlace como)", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TAI: La objetización de las personas" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/tia.html#entregar", - "href": "pages/Bloque2/tia.html#entregar", - "title": "TAI: La objetización de las personas", - "section": "Entregar", - "text": "Entregar\nSe debe entregar un único archivo de JavaScript (.js) que contenga la solución completa a la tarea.", + "objectID": "pages/Bloque2/intensivo.html#variables-y-tipos-básicos", + "href": "pages/Bloque2/intensivo.html#variables-y-tipos-básicos", + "title": "Repaso Intensivo JS", + "section": "Variables y tipos básicos", + "text": "Variables y tipos básicos\n\nDeclaración de variables\nEn JavaScript moderno se utilizan let y const (evitar var).\n\nlet: permite reasignación\nconst: no permite reasignación\nconst NO significa inmutable\nJavaScript es de tipado dinámico\nEl tipo depende del valor, no de la variable\n\nTipos primitivos:\n\nstring\nnumber\nboolean\nnull\nundefined\n\nlet edad = 12; // number\nlet altura = 1.8; // number\nlet nombre = \"Javier\"; // string\nlet casado = false; // boolean\n\nlet ordenador = null; // ausencia intencionada de valor\nlet direccion; // undefined\n\n\nUso de const\nconst dni = \"1235678L\";\ndni = \"23\"; // Error\n\nconst no significa inmutable\nconst dni = \"12345678L\";\ndni = \"87654321X\"; // Error\nPero:\nconst arr = [1, 2, 3];\narr.push(4); // permitido\n\n\n\nTipado dinámico\n\nJavaScript es de tipado dinámico\nEl tipo depende del valor, no de la variable\nUna variable puede cambiar de tipo durante la ejecución\n\nlet x = \"hola\";\nx = 42; // válido\nx = true; // válido\nEste comportamiento se conoce como shadowing o cambio dinámico de tipo. En el ejemplo anterior solo existe una variable X cuyo tipo pasa de Number a boolean", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TAI: La objetización de las personas" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/tia.html#realización-de-la-tarea", - "href": "pages/Bloque2/tia.html#realización-de-la-tarea", - "title": "TAI: La objetización de las personas", - "section": "Realización de la tarea", - "text": "Realización de la tarea\nEl archivo JavaScript debe estar claramente dividido en dos partes:\n\nla implementación de clases, donde se definirán todas las clases necesarias\n\nla zona de uso, donde se utilizarán las clases previamente definidas\n\n\nImplementación de clases\nTodas las clases deberán definirse utilizando la sintaxis de clases ES6, haciendo uso correcto de:\n\nclass\nextends\nsuper\npropiedades privadas (usando #)\ngetters y setters (get y set)\nmétodos estáticos\n\n\nClase Person\nDebe contener:\n\npropiedad privada name\npropiedad privada dni\nSe puede obtener tanto el nombre como el DNI, pero solo se puede modificar el nombre\nEl constructor recibirá:\n\nun nombre\nun NÚMERO de DNI\n\nEl constructor deberá calcular automáticamente la letra del DNI siguiendo el algoritmo oficial:\nhttps://www.interior.gob.es/opencms/es/servicios-al-ciudadano/tramites-y-gestiones/dni/calculo-del-digito-de-control-del-nif-nie/\nMétodos y accesos:\n\ngetter name\nsetter name\ngetter dni\nmétodo getInfo() que devuelva un string con el nombre y el DNI completo\n\nSi los datos introducidos no son válidos, se lanzará un Error\n\n\n\nClase Member (clase hija de Person)\nRepresenta a un miembro del equipo de Hyperloop.\nDebe contener:\n\npropiedad privada department\npropiedad privada yearsExperience\n\n\nDepartamentos válidos\nLos únicos departamentos permitidos son:\n\n\"Managment\"\n\"Operaciones\"\n\"Avionics\"\n\"Electromagnetics\"\n\"Mechanics\"\n\nNo se permitirá ningún otro valor.\n\n\nRequisitos adicionales\n\nLa propiedad department:\n\nse accederá mediante:\n\ngetter department\nsetter department\n\n\nEl setter validará que el departamento sea válido\nyearsExperience debe ser un número mayor o igual que 0\n\n\n\nMétodo estático obligatorio\nLa clase Member debe incluir el siguiente método estático:\n\nisValidDepartment(department)\n\ndevuelve true si el departamento es válido\ndevuelve false en caso contrario\ndeberá utilizarse tanto en el constructor como en el setter de department\n\n\n\n\nMétodos públicos\n\ngetter yearsExperience\nmétodo getInfo():\n\nsobrescribe el método de Person\nincluye el departamento y los años de experiencia\n\n\n\n\n\nClase Engineer (clase hija de Member)\nRepresenta a un ingeniero del equipo.\nDebe contener:\n\npropiedad privada specialty\nLa especialidad será un string no vacío\n\n\nAccesos y métodos\n\ngetter specialty\nmétodo getInfo():\n\nsobrescribe el método anterior\nincluye la especialidad del ingeniero\n\n\n\n\n\nClase Team\nRepresenta el equipo completo de Hyperloop.\nDebe contener:\n\npropiedad privada members, que será un array de objetos Member\n\n\nMétodos públicos\n\naddMember(member)\n\nsolo permite añadir objetos que sean instancia de Member\n\nremoveMemberByDni(dni)\nlistMembers()\n\nmuestra por consola la información de todos los miembros del equipo\n\ncountMembersByDepartment(department)\n\ndevuelve cuántos miembros pertenecen a un determinado departamento\n\n\n\n\n\n\nZona de uso\nEn la zona de uso del archivo JavaScript se debe:\n\nCrear al menos:\n\n2 objetos Engineer de departamentos distintos\n1 objeto Member que no sea ingeniero\n\nCrear un objeto Team\nAñadir los miembros al equipo\nUtilizar explícitamente:\n\ngetters\nsetters\nel método estático de validación\n\nMostrar por consola:\n\nel listado completo del equipo\nel número de miembros por departamento\n\nProbar al menos un caso incorrecto:\n\npor ejemplo, asignar un departamento no válido\no intentar añadir un objeto que no sea Member\n\nDemostrar que el error se gestiona correctamente", + "objectID": "pages/Bloque2/intensivo.html#null-vs-undefined", + "href": "pages/Bloque2/intensivo.html#null-vs-undefined", + "title": "Repaso Intensivo JS", + "section": "null vs undefined", + "text": "null vs undefined\n\nundefined: variable declarada pero sin valor\nnull: ausencia intencionada de valor\n\nJavaScript distingue entre:\n\n“todavía no hay valor” y “no hay valor”\n\nconsole.log(ordenador); // null\nconsole.log(direccion); // undefined", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TAI: La objetización de las personas" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/tia.html#apéndice-comprobaciones-y-errores-en-javascript-necesario-para-la-tarea", - "href": "pages/Bloque2/tia.html#apéndice-comprobaciones-y-errores-en-javascript-necesario-para-la-tarea", - "title": "TAI: La objetización de las personas", - "section": "Apéndice: comprobaciones y errores en JavaScript (NECESARIO PARA LA TAREA)", - "text": "Apéndice: comprobaciones y errores en JavaScript (NECESARIO PARA LA TAREA)\nEn el desarrollo de la tarea pueden aparecer algunas comprobaciones y mecanismos de control de errores que es necesario saber implementar por cuenta propia. Su inclusión tiene como objetivo facilitar la robustez del código, y forman parte de los contenidos evaluables de la tarea.\n\nUso de Error\nCuando se detecta una situación incorrecta (por ejemplo, un valor no válido o un uso indebido de una clase), se puede lanzar un error utilizando:\nthrow new Error(\"Mensaje de error\");\nEsto indica claramente que algo no es correcto y detiene la ejecución normal del programa.\n\n\nUso de instanceof\nEl operador instanceof se utiliza para comprobar si un objeto ha sido creado a partir de una clase concreta.\nobjeto instanceof Clase\nDevuelve true si el objeto pertenece a esa clase y false en caso contrario.\n\n\nUso de typeof\nEl operador typeof permite comprobar el tipo de datos simples como strings o números.\ntypeof variable\nEjemplos:\ntypeof \"texto\" // \"string\"\ntypeof 10 // \"number\"\nSe utiliza para validar los datos recibidos por constructores o setters. Para comprobar clases u objetos personalizados debe usarse instanceof, no typeof.", + "objectID": "pages/Bloque2/intensivo.html#aritmética-y-operadores", + "href": "pages/Bloque2/intensivo.html#aritmética-y-operadores", + "title": "Repaso Intensivo JS", + "section": "Aritmética y operadores", + "text": "Aritmética y operadores\n\nOperadores aritméticos\nlet a = 12, b = 4;\n\na + b\na - b\na * b\na / b\na % b\na = a + b;\na += b;\na -= b;\na *= b;\n\nPotencias\na**b // Power\nIncrementos:\nb--; b++;\n--b; ++b;\n\n\n\nStrings y concatenación\na = \"hola \";\nb = \"mundo\";\na + b;\n\n\nComparación\n\n== compara valor (evitar)\n=== compara valor y tipo (usar)\n\n\n\nOperadores lógicos\n\n&& AND\n|| OR\n! NOT\n\n\n\nComparaciones\n\n== compara solo valor (evitar)\n=== compara valor y tipo (usar siempre, aunque sea innecesario)\n\n5 == \"5\"; // true\n5 === \"5\"; // false\n\n\nOperadores lógicos\n\n&& AND\n|| OR\n! NOT\n\n(a > 0) && (b < 10)", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TAI: La objetización de las personas" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html", - "href": "pages/Bloque2/MAclases.html", - "title": "MA: Clases ES6", - "section": "", - "text": "Contenido\nRepaso intensivo de clases en JavaScript (ES6+), orientado a usuarios con experiencia previa en programación y familiarizados con funciones, objetos y arrays.", + "objectID": "pages/Bloque2/intensivo.html#estructuras-de-control", + "href": "pages/Bloque2/intensivo.html#estructuras-de-control", + "title": "Repaso Intensivo JS", + "section": "Estructuras de control", + "text": "Estructuras de control\n\nCondicionales\nif (a === b) {\n\n} else if (a > b) {\n\n} else {\n\n}\n\n\nBucles\n\nwhile\nlet x = 20;\nwhile (x < 50) {\n x += 10;\n}\n\n\nfor\nfor (let i = 0; i < 10; i++) {\n // iteración\n}", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#programación-orientada-a-objetos-en-javascript", - "href": "pages/Bloque2/MAclases.html#programación-orientada-a-objetos-en-javascript", - "title": "MA: Clases ES6", - "section": "Programación orientada a objetos en JavaScript", - "text": "Programación orientada a objetos en JavaScript\nJavaScript es un lenguaje basado en prototipos, pero desde ES6 introduce la sintaxis class, que:\n\nEs azúcar sintáctico sobre el sistema de prototipos\nFacilita la escritura y lectura de código OO\nNo convierte a JS en un lenguaje basado en clases clásicas", + "objectID": "pages/Bloque2/intensivo.html#funciones", + "href": "pages/Bloque2/intensivo.html#funciones", + "title": "Repaso Intensivo JS", + "section": "Funciones", + "text": "Funciones\n\nEncapsulan lógica reutilizable\nPueden recibir parámetros\nPueden devolver valores\nSon ciudadanos de primera clase\n\n\nFunción clásica\nfunction sumar2(num, num2 = 2) {\n num += num2;\n return num;\n}\nPaso de variables por valor:\nlet a = 7;\nlet b = sumar2(a, a); // 14\na; // 7\n\n\nFunciones flecha y orden superior\nconst concatenarHola = input => input + \" Hola\";\nconcatenarHola(\"sdf\");\nfunction ejecuta(fun) {\n fun();\n}\n\nejecuta(() => { console.log(\"hola\"); });\n\n\nFunciones propias de strings\nlet a = \"jsadfsadf \";\na.trim(); // Suprimir espacios adicionales\na.split('a'); // Divide el string en un array c\na.length;\n\n\nFunciones flecha\nconst cuadrado = n => n ** 2;\nForma extendida:\nconst cuadrado = (n) => {\n return n ** 2;\n};\n\n\nFunciones como ciudadanos de primera clase\nLas funciones pueden:\n\nAsignarse a variables\nPasarse como argumentos\nDevolverse como resultado\n\nfunction ejecutar(f) {\n f();\n}\n\nejecutar(() => console.log(\"Hola\"));", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#definición-de-una-clase", - "href": "pages/Bloque2/MAclases.html#definición-de-una-clase", - "title": "MA: Clases ES6", - "section": "Definición de una clase", - "text": "Definición de una clase\n\nSintaxis básica\nclass Persona {\n constructor(nombre, edad) {\n this.nombre = nombre;\n this.edad = edad;\n }\n}\n\nclass: palabra clave\nconstructor: método especial de inicialización\nthis: referencia a la instancia actual", + "objectID": "pages/Bloque2/intensivo.html#arrays-base", + "href": "pages/Bloque2/intensivo.html#arrays-base", + "title": "Repaso Intensivo JS", + "section": "Arrays (base)", + "text": "Arrays (base)\n\nLista ordenada\nÍndices empiezan en 0\nPropiedad length\n\nlet cajon = [8, \"hola\", true, () => { return 7 }];\n\nAcceso\ncajon[0] // 8\ncajon[2] = \"rino\"; // modificamos la entrada 2 \n\n\nAdiciones\ncajon.push(false);\ncajon.unshift(0);\n\n\nEliminaciones\ncajon.pop();\ncajon.shift();\ncajon.length;", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#creación-de-instancias", - "href": "pages/Bloque2/MAclases.html#creación-de-instancias", - "title": "MA: Clases ES6", - "section": "Creación de instancias", - "text": "Creación de instancias\nconst p1 = new Persona(\"Javier\", 45);\nconst p2 = new Persona(\"Ana\", 32);\n\nnew crea un nuevo objeto\nEjecuta automáticamente constructor", + "objectID": "pages/Bloque2/intensivo.html#objetos", + "href": "pages/Bloque2/intensivo.html#objetos", + "title": "Repaso Intensivo JS", + "section": "Objetos", + "text": "Objetos\nUn objeto representa una entidad mediante estructura clave–valor.\nlet gente = { pepe: 7, juanes: 8, andreas: 10, fran: [4, 2] };\n\nModificación\ngente.andreas = 32;\ngente.pepe++;\n\n\nAcceso dinámico\nlet nombre = \"pablo\";\n\ngente.nombre; // undefined\ngente[nombre] = 2; // añade propiedad", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#métodos-de-instancia", - "href": "pages/Bloque2/MAclases.html#métodos-de-instancia", - "title": "MA: Clases ES6", - "section": "Métodos de instancia", - "text": "Métodos de instancia\nLos métodos se definen sin function y se comparten vía prototipo.\nclass Persona {\n constructor(nombre, edad) {\n this.nombre = nombre;\n this.edad = edad;\n }\n\n saludar() {\n return `Hola, soy ${this.nombre}`;\n }\n\n cumple() {\n this.edad++;\n }\n}\nUso:\np1.saludar();\np1.cumple();", + "objectID": "pages/Bloque2/intensivo.html#referencias-vs-valores", + "href": "pages/Bloque2/intensivo.html#referencias-vs-valores", + "title": "Repaso Intensivo JS", + "section": "Referencias vs valores", + "text": "Referencias vs valores\n\nCopia por valor\nlet a = 5;\nlet b = a;\nb++;\na no cambia.\n\n\nCopia por referencia\nlet e3 = [\"juan\", \"pepe\"];\nlet d = e3;\n\nd.push(\"andrés\");\nAmbas variables apuntan al mismo array.\nconst poblacion = gente;\npoblacion[\"julio\"] = 8;\nLa copia por refencia se aplica a objetos y arrays\nlet x = [\"juan\", \"pepe\"];\nlet y = x;\n\ny.push(\"andrés\"); // Se añade en x e y pues son el mismo objeto\nAmbas variables apuntan al mismo objeto.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#métodos-vs-funciones-flecha", - "href": "pages/Bloque2/MAclases.html#métodos-vs-funciones-flecha", - "title": "MA: Clases ES6", - "section": "Métodos vs funciones flecha", - "text": "Métodos vs funciones flecha\nNo usar arrow functions como métodos de clase (salvo casos concretos):\nclass MalEjemplo {\n metodo = () => {\n console.log(this);\n };\n}\n\nRompe el modelo prototípico\nMayor consumo de memoria", + "objectID": "pages/Bloque2/intensivo.html#spread-operator-...", + "href": "pages/Bloque2/intensivo.html#spread-operator-...", + "title": "Repaso Intensivo JS", + "section": "Spread operator (...)", + "text": "Spread operator (...)\n\nExpande arrays u objetos\nPermite copiar y combinar\nCopia superficial\n\n\nArrays\nJavier es añadido a arr2, pero no a arr.\nlet arr = [\"Alice\", \"Bob\", \"Kevin\"];\nlet arr2 = [...arr, \"Javier\"];\n\n\nObjetos\nOcurre lo mismo con los objetos\nconst sociedad = { ...poblacion, julia: 12 };", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#propiedades-públicas", - "href": "pages/Bloque2/MAclases.html#propiedades-públicas", - "title": "MA: Clases ES6", - "section": "Propiedades públicas", - "text": "Propiedades públicas\nLas propiedades se suelen declarar en el constructor:\nclass Coche {\n constructor(marca, km = 0) {\n this.marca = marca;\n this.km = km;\n }\n}\nUso:\nconst c = new Coche(\"Toyota\");\nc.km += 100;", + "objectID": "pages/Bloque2/intensivo.html#funciones-de-array-js-moderno", + "href": "pages/Bloque2/intensivo.html#funciones-de-array-js-moderno", + "title": "Repaso Intensivo JS", + "section": "Funciones de array (JS moderno)", + "text": "Funciones de array (JS moderno)\nVamos a trabajar con un ejemplo completo, típico en programación funcional.\n\nDatos de partida\nlet y = [2, 4, 6, 7];\n\n\nFunción cuadrado\nDefinimos una función que, dado un número, devuelve su cuadrado:\nconst cuadrado = n => n ** 2;\nEs equivalente a:\nconst cuadrado = (n) => {\n return n ** 2;\n};\n\n\nmap: transformar elementos\nAplicamos map para obtener un nuevo array con los cuadrados:\nconst y2 = y.map(cuadrado);\nResultado:\n[4, 16, 36, 49]\n\n\nfilter: seleccionar elementos\nDefinimos una función que comprueba si un número es par:\nconst even = n => n % 2 === 0;\nLa usamos con filter:\nconst yEven = y.filter(even);\n\n\nEncadenamiento (estilo declarativo)\nPodemos encadenar ambas operaciones:\ny\n .map(n => n ** 2)\n .filter(n => n % 2 === 0);\n\nEste estilo es declarativo: describimos qué queremos hacer con los datos, no cómo recorrerlos.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#getters-y-setters", - "href": "pages/Bloque2/MAclases.html#getters-y-setters", - "title": "MA: Clases ES6", - "section": "Getters y setters", - "text": "Getters y setters\nPermiten acceder como propiedades a lógica encapsulada.\nclass Rectangulo {\n constructor(ancho, alto) {\n this.ancho = ancho;\n this.alto = alto;\n }\n\n get area() {\n return this.ancho * this.alto;\n }\n\n set escala(factor) {\n this.ancho *= factor;\n this.alto *= factor;\n }\n}\nUso:\nconst r = new Rectangulo(2, 3);\nr.area; // 6\nr.escala = 2;\nr.area; // 24", - "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" - ] + "objectID": "pages/Bloque3/intermedio.html#controlled-inputs", + "href": "pages/Bloque3/intermedio.html#controlled-inputs", + "title": "React III", + "section": "Controlled Inputs", + "text": "Controlled Inputs\nMotivación\nHasta ahora se ha trabajado con eventos capturando acciones del usuario.\nSin embargo, al trabajar con formularios surge una cuestión fundamental:\n\n¿Quién controla el valor del input?\n¿El DOM o React?" + }, + { + "objectID": "pages/Bloque3/intermedio.html#hooks-repaso", + "href": "pages/Bloque3/intermedio.html#hooks-repaso", + "title": "React III", + "section": "Hooks (Repaso)", + "text": "Hooks (Repaso)\n\nFunción especial que permite modificar las propiedades internas de los componentes\nCaracterísticas avanzadas\nModificación del life-cycle\nNormalmente forma use____" + }, + { + "objectID": "pages/Bloque3/intermedio.html#useeffect", + "href": "pages/Bloque3/intermedio.html#useeffect", + "title": "React III", + "section": "useEffect", + "text": "useEffect\n\nuseEffect es un Hook que permite ejecutar efectos secundarios dentro de un componente funcional.\nUn efecto secundario es cualquier operación que no sea simplemente devolver JSX (por ejemplo: peticiones a un servidor, temporizadores, suscripciones).\nSe ejecuta después de que el componente se renderiza en el DOM." + }, + { + "objectID": "pages/Bloque3/intermedio.html#fetch", + "href": "pages/Bloque3/intermedio.html#fetch", + "title": "React III", + "section": "fetch()", + "text": "fetch()\nHasta ahora nuestros componentes eran completamente locales.\nSin embargo, en aplicaciones reales necesitamos:\n\nDescargar datos\n\nConectarnos a servidores\n\nTrabajar con APIs externas\n\nPara ello utilizamos fetch()." + }, + { + "objectID": "pages/Bloque3/intermedio.html#async-y-await", + "href": "pages/Bloque3/intermedio.html#async-y-await", + "title": "React III", + "section": "async y await", + "text": "async y await\nHasta ahora hemos utilizado fetch() con encadenamiento.\nExiste una forma más clara y estructurada de escribir código asíncrono:\n\nasync\nawait\n\nSu objetivo es hacer que el código sea más legible." }, { - "objectID": "pages/Bloque2/MAclases.html#herencia-extends", - "href": "pages/Bloque2/MAclases.html#herencia-extends", - "title": "MA: Clases ES6", - "section": "Herencia (extends)", - "text": "Herencia (extends)\nJavaScript soporta herencia simple.\nclass Empleado extends Persona {\n constructor(nombre, edad, salario) {\n super(nombre, edad);\n this.salario = salario;\n }\n\n salarioAnual() {\n return this.salario * 12;\n }\n}\n\nextends: herencia\nsuper(): llama al constructor padre (obligatorio)", + "objectID": "pages/Bloque3/intermedio.html#ejemplo-con-la-pokeapi", + "href": "pages/Bloque3/intermedio.html#ejemplo-con-la-pokeapi", + "title": "React III", + "section": "Ejemplo con la Pokeapi", + "text": "Ejemplo con la Pokeapi\nPoke-API\nDownload Code" + }, + { + "objectID": "pages/Bloque3/Intermedio.html", + "href": "pages/Bloque3/Intermedio.html", + "title": "React III", + "section": "", + "text": "Contenido", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#sobrescritura-de-métodos", - "href": "pages/Bloque2/MAclases.html#sobrescritura-de-métodos", - "title": "MA: Clases ES6", - "section": "Sobrescritura de métodos", - "text": "Sobrescritura de métodos\nclass Empleado extends Persona {\n saludar() {\n return `Empleado: ${this.nombre}`;\n }\n}\n\nSi el método existe en la clase hija, sobrescribe al del padre", + "objectID": "pages/Bloque3/Intermedio.html#controlled-inputs", + "href": "pages/Bloque3/Intermedio.html#controlled-inputs", + "title": "React III", + "section": "Controlled Inputs", + "text": "Controlled Inputs\n\nMotivación\nHasta ahora se ha trabajado con eventos capturando acciones del usuario.\nSin embargo, al trabajar con formularios surge una cuestión fundamental:\n\n¿Quién controla el valor del input?\n¿El DOM o React?\n\nRecordemos que en HTML puro o, el valor de un <input> está gestionado directamente por el DOM.\nEn React, podemos hacer que el valor del input esté controlado por el estado del componente.\nA esto lo llamamos controlled input.\n\n\n¿Qué es un controlled input?\nUn controlled input es un elemento de formulario cuyo valor:\n\nEstá almacenado en el estado del componente\nSe actualiza mediante un evento (onChange)\nSe renderiza utilizando ese mismo estado\n\nÚnica fuente de verdad (single source of truth).\n\n\nEstructura del componente controlled\nimport { useState } from \"react\";\nfunction FormularioNombre() {\n\n const [nombre, setNombre] = useState(\"\");\n\n function manejarCambio(event) {\n setNombre(event.target.value);\n }\n\n return (\n <div>\n <input type=\"text\" \n value={nombre}\n onChange={manejarCambio}\n />\n <p>El nombre introducido es: {nombre}</p>\n </div>\n );\n}\n\nAnálisis del ejemplo\nEl valor del input se sincroniza con el estado\n\nDeclaramos una variable de estado: nombre\nAsociamos el atributo value del input a ese estado\nCapturamos el evento onChange\nActualizamos el estado con setNombre\n\nCada vez que el estado cambia: El componente se vuelve a ejecutar El JSX se vuelve a generar El valor del input se sincroniza con el estado\n\n\n\nEjemplo Formulario\nimport { useState } from \"react\";\n\nfunction FormularioSimple() {\n\n const [email, setEmail] = useState(\"\");\n\n function handleChange(event) {\n setEmail(event.target.value);\n }\n\n function handleSubmit(event) {\n event.preventDefault(); // Evita la recarga del navegador\n\n console.log(\"Formulario enviado\");\n console.log(\"Email:\", email);\n\n setEmail(\"\"); // Limpieza opcional del campo\n }\n\n return (\n <form onSubmit={handleSubmit}>\n <input \n type=\"email\"\n value={email}\n onChange={handleChange}\n />\n <button type=\"submit\">Enviar</button>\n </form>\n );\n}\nReferencia: https://es.react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#uso-de-super-en-métodos", - "href": "pages/Bloque2/MAclases.html#uso-de-super-en-métodos", - "title": "MA: Clases ES6", - "section": "Uso de super en métodos", - "text": "Uso de super en métodos\nclass Empleado extends Persona {\n saludar() {\n return super.saludar() + \" (empleado)\";\n }\n}\nPermite reutilizar lógica del padre.", + "objectID": "pages/Bloque3/Intermedio.html#hooks-repaso", + "href": "pages/Bloque3/Intermedio.html#hooks-repaso", + "title": "React III", + "section": "Hooks (Repaso)", + "text": "Hooks (Repaso)\n\nFunción especial que permite modificar las propiedades internas de los componentes\nCaracterísticas avanzadas\nModificación del life-cycle\nNormalmente forma use____", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#métodos-estáticos", - "href": "pages/Bloque2/MAclases.html#métodos-estáticos", - "title": "MA: Clases ES6", - "section": "Métodos estáticos", - "text": "Métodos estáticos\nPertenecen a la clase, no a las instancias.\nclass Utilidades {\n static suma(a, b) {\n return a + b;\n }\n}\nUso:\nUtilidades.suma(2, 3);\nNo accesible desde instancias:\nnew Utilidades().suma; // undefined", + "objectID": "pages/Bloque3/Intermedio.html#useeffect", + "href": "pages/Bloque3/Intermedio.html#useeffect", + "title": "React III", + "section": "useEffect", + "text": "useEffect\n\nuseEffect es un Hook que permite ejecutar efectos secundarios dentro de un componente funcional.\nUn efecto secundario es cualquier operación que no sea simplemente devolver JSX (por ejemplo: peticiones a un servidor, temporizadores, suscripciones).\nSe ejecuta después de que el componente se renderiza en el DOM.\n\n\nMétodos de uso de useEffect\n\n1. Sin array de dependencias\nuseEffect(() => {\n console.log(\"Se ejecuta en cada render\");\n});\nComportamiento:\n\nSe ejecuta después de cada renderizado.\nNo existe control sobre la frecuencia.\nPuede generar bucles si modifica estado sin control.\n\nInterpretación conceptual:\nEl efecto acompaña siempre al render.\n\n\n2. Con array vacío\nuseEffect(() => {\n console.log(\"Se ejecuta solo una vez\");\n}, []);\nComportamiento:\n\nSe ejecuta únicamente tras el primer render.\nEquivalente conceptual al “montaje” del componente.\n\nUso habitual:\n\nPeticiones a servidor\nInicializaciones\nSuscripciones\n\nInterpretación conceptual:\nEl efecto ocurre una única vez al crear el componente.\n\n\n3. Con dependencias específicas\nuseEffect(() => {\n console.log(\"Se ejecuta cuando cambia contador\");\n}, [contador]);\nComportamiento:\n\nSe ejecuta tras el primer render.\nSe vuelve a ejecutar cuando cambia alguna variable del array.\n\nInterpretación conceptual:\nEl efecto depende del estado indicado.\nReact compara el valor anterior con el nuevo y decide si debe ejecutar el efecto.", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#campos-privados", - "href": "pages/Bloque2/MAclases.html#campos-privados", - "title": "MA: Clases ES6", - "section": "Campos privados (#)", - "text": "Campos privados (#)\nIntroducidos en ES2022.\nclass Cuenta {\n #saldo = 0;\n\n ingresar(cantidad) {\n this.#saldo += cantidad;\n }\n\n getSaldo() {\n return this.#saldo;\n }\n}\n\n#saldo es realmente privado\nNo accesible fuera de la clase", + "objectID": "pages/Bloque3/Intermedio.html#fetch", + "href": "pages/Bloque3/Intermedio.html#fetch", + "title": "React III", + "section": "fetch()", + "text": "fetch()\nHasta ahora nuestros componentes eran completamente locales.\nSin embargo, en aplicaciones reales necesitamos:\n\nDescargar datos\n\nConectarnos a servidores\n\nTrabajar con APIs externas\n\nPara ello utilizamos fetch().\n\nEjemplo mínimo de fetch\nfetch(\"https://pokeapi.co/api/v2/pokemon/1\")\n .then(response => response.json())\n .then(data => console.log(data));\nUtiliza las Promises\nInterpretación simple:\n\nSe hace una petición a una URL\n\nSe transforma la respuesta a formato JSON\n\nSe accede a los datos\n\n\n\nfetch() dentro de useEffect\nEn React, lo habitual es realizar la descarga cuando el componente se monta.\nPara ello:\n\nUtilizamos useEffect\nAñadimos array vacío []\nGuardamos los datos en el estado\n\n\n\nEjemplo integrado\nimport { useState, useEffect } from \"react\";\n\nfunction Pokemon() {\n\n const [pokemon, setPokemon] = useState(null);\n\n useEffect(() => {\n\n fetch(\"https://pokeapi.co/api/v2/pokemon/1\")\n .then(response => response.json())\n .then(data => setPokemon(data));\n\n }, []);\n\n if (!pokemon) return <p>Cargando...</p>;\n\n return (\n <div>\n <h2>{pokemon.name}</h2>\n <img \n src={pokemon.sprites.front_default} \n alt={pokemon.name} \n />\n </div>\n );\n}\n\n\nFlujo conceptual\n\nRender inicial\n\nSe ejecuta useEffect\n\nSe lanza la petición\n\nSe actualiza el estado\n\nNuevo render con los datos\n\n\n\nAdvertencia importante\nSi eliminamos el array vacío:\nuseEffect(() => {\n fetch(\"https://pokeapi.co/api/v2/pokemon/1\")\n .then(res => res.json())\n .then(data => setPokemon(data));\n});\nEl efecto se ejecutará en cada render.\nComo actualizar estado provoca render, se generará un bucle infinito.\nuseEffect conecta React con el exterior.\nfetch() permite traer datos del exterior.\nEl estado vuelve a controlar el render.\nEn la siguiente sección formalizaremos esto utilizando async / await.", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#clases-y-objetos-literales", - "href": "pages/Bloque2/MAclases.html#clases-y-objetos-literales", - "title": "MA: Clases ES6", - "section": "Clases y objetos literales", - "text": "Clases y objetos literales\nEsto:\nconst a = {\n x: 1,\n inc() { this.x++; }\n};\nEs equivalente conceptualmente a una instancia única.\nUsar class cuando:\n\nHay múltiples instancias\nExiste estado y comportamiento común\nSe necesita herencia o abstracción", + "objectID": "pages/Bloque3/Intermedio.html#async-y-await", + "href": "pages/Bloque3/Intermedio.html#async-y-await", + "title": "React III", + "section": "async y await", + "text": "async y await\nHasta ahora hemos utilizado fetch() con encadenamiento.\nExiste una forma más clara y estructurada de escribir código asíncrono:\n\nasync\nawait\n\nSu objetivo es hacer que el código sea más legible.\n\n¿Qué significa async?\n\nSe coloca delante de una función\nIndica que la función trabajará con operaciones asíncronas\n\nasync function ejemplo() {\n console.log(\"Función asíncrona\");\n}\n\n\n¿Qué significa await?\n\nSolo puede utilizarse dentro de una función async\nDetiene la ejecución hasta que la operación finaliza\nHace que el código se lea de forma secuencial\n\n\n\nEjemplo básico con fetch\nasync function obtenerPokemon() {\n\n const response = await fetch(\n \"https://pokeapi.co/api/v2/pokemon/1\"\n );\n\n const data = await response.json();\n\n console.log(data);\n}\nInterpretación conceptual:\n\nSe realiza la petición\nSe espera la respuesta\nSe transforma a JSON\nSe trabaja con los datos\n\nEl código se lee de arriba hacia abajo.\n\n\nasync / await dentro de useEffect\nEn React, lo habitual es declarar una función interna y ejecutarla.\n\n\nEjemplo completo\nimport { useState, useEffect } from \"react\";\n\nfunction Pokemon() {\n\n const [pokemon, setPokemon] = useState(null);\n\n useEffect(() => {\n\n async function fetchData() {\n\n const response = await fetch(\n \"https://pokeapi.co/api/v2/pokemon/1\"\n );\n\n const data = await response.json();\n\n setPokemon(data);\n }\n\n fetchData();\n\n }, []);\n\n if (!pokemon) return <p>Cargando...</p>;\n\n return (\n <div>\n <h2>{pokemon.name}</h2>\n <img \n src={pokemon.sprites.front_default} \n alt={pokemon.name} \n />\n </div>\n );\n}\n\n\n¿Por qué no hacer directamente?\nuseEffect(async () => {\n ...\n}, []);\nPorque useEffect no debe recibir una función asíncrona directamente.\nPor eso declaramos la función dentro y luego la ejecutamos.\n\n\nFlujo mental con async / await\n\nRender inicial\n\nSe ejecuta useEffect\n\nSe llama a la función asíncrona\n\nawait espera la respuesta\n\nSe actualiza el estado\n\nNuevo render\n\nasync / await no cambia lo que hace el programa.\nSolo cambia la forma de escribirlo:\nMás claro.\nMás estructurado.\nMás fácil de mantener.", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#clases-prototípicas-pre-es6", - "href": "pages/Bloque2/MAclases.html#clases-prototípicas-pre-es6", - "title": "MA: Clases ES6", - "section": "Clases prototípicas (pre-ES6)", - "text": "Clases prototípicas (pre-ES6)\nJavaScript siempre ha sido un lenguaje basado en prototipos. Antes de ES6, la creación de objetos y herencia se realizaba mediante funciones constructoras y el prototipo.\nEn este repaso no entraremos en detalle en este modelo.\nBasta con saber que:\n\nLas clases ES6 no sustituyen al modelo prototípico\nSon una capa de abstracción sobre él\nTodo el comportamiento sigue resolviéndose vía prototipos\n\nPara profundizar:\n\nhttps://developer.mozilla.org/es/docs/Web/JavaScript/Inheritance_and_the_prototype_chain\n\nfunction Persona(nombre) {\nthis.nombre = nombre;\n}\n\nPersona.prototype.saludar = function () {\nreturn this.nombre;\n};\nvs\nclass Persona {\n constructor(nombre) {\n this.nombre = nombre;\n }\n\n saludar() {\n return this.nombre;\n }\n}", + "objectID": "pages/Bloque3/Intermedio.html#ejemplo-con-la-pokeapi", + "href": "pages/Bloque3/Intermedio.html#ejemplo-con-la-pokeapi", + "title": "React III", + "section": "Ejemplo con la Pokeapi", + "text": "Ejemplo con la Pokeapi\nPoke-API\nDownload Code", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { @@ -1121,167 +1377,84 @@ ] }, { - "objectID": "pages/Bloque3/dom.html#qué-es-el-dom", - "href": "pages/Bloque3/dom.html#qué-es-el-dom", - "title": "DOM", - "section": "¿Qué es el DOM?", - "text": "¿Qué es el DOM?\nEl DOM (Document Object Model) es la representación en memoria que el navegador crea a partir del HTML.\n\nEl HTML es estático\nEl DOM es dinámico\nJavaScript interactúa con el DOM, no con el HTML original\n\n\nEl DOM es la página web viva dentro del navegador." - }, - { - "objectID": "pages/Bloque3/dom.html#el-dom-como-árbol", - "href": "pages/Bloque3/dom.html#el-dom-como-árbol", - "title": "DOM", - "section": "El DOM como árbol", - "text": "El DOM como árbol\nEl DOM tiene estructura de árbol (grafo):\n\nCada etiqueta HTML es un nodo\nLos nodos tienen relaciones (padre, hijos, hermanos)\n\nEjemplo:\n<body>\n <h1>Título</h1>\n <button>Click</button>\n</body>" - }, - { - "objectID": "pages/Bloque3/dom.html#acceso-al-dom-desde-javascript", - "href": "pages/Bloque3/dom.html#acceso-al-dom-desde-javascript", - "title": "DOM", - "section": "Acceso al DOM desde JavaScript", - "text": "Acceso al DOM desde JavaScript\nEl navegador nos proporciona el objeto global document, que permite:\n\nBuscar elementos\nLeer su contenido\nModificar la interfaz\n\ndocument\ndocument.body" - }, - { - "objectID": "pages/Bloque3/dom.html#selectores", - "href": "pages/Bloque3/dom.html#selectores", - "title": "DOM", - "section": "Selectores", - "text": "Selectores\nPor ID\ndocument.getElementById(\"count\")\ndocument.querySelector(\"#count\")\nPor etiqueta\ndocument.querySelector(\"button\")" - }, - { - "objectID": "pages/Bloque3/dom.html#leer-y-modificar-elementos", - "href": "pages/Bloque3/dom.html#leer-y-modificar-elementos", - "title": "DOM", - "section": "Leer y modificar elementos", - "text": "Leer y modificar elementos\nelement.textContent\nelement.textContent = \"Nuevo texto\"\nelement.classList.add(\"active\")\nelement.classList.remove(\"active\")" - }, - { - "objectID": "pages/Bloque3/dom.html#eventos", - "href": "pages/Bloque3/dom.html#eventos", - "title": "DOM", - "section": "Eventos", - "text": "Eventos\nEl DOM permite reaccionar a acciones del usuario mediante eventos.\nbutton.addEventListener(\"click\", () => {\n // código a ejecutar\n});\nFlujo típico:\nUsuario → Evento → JavaScript → DOM actualizado" - }, - { - "objectID": "pages/Bloque3/dom.html#ejemplo-contador-con-botón", - "href": "pages/Bloque3/dom.html#ejemplo-contador-con-botón", - "title": "DOM", - "section": "Ejemplo: contador con botón", - "text": "Ejemplo: contador con botón\nHTML\n<h1 id=\"count\">0</h1>\n<button id=\"btn\">Sumar 1</button>\nJavaScript\nlet count = 0;\n\nconst countEl = document.querySelector(\"#count\");\nconst btn = document.querySelector(\"#btn\");\n\nbtn.addEventListener(\"click\", () => {\n count++;\n countEl.textContent = count;\n});" - }, - { - "objectID": "pages/Bloque3/dom.html#más-ejemplos", - "href": "pages/Bloque3/dom.html#más-ejemplos", - "title": "DOM", - "section": "Más ejemplos", - "text": "Más ejemplos\nEj1: Show input\nEj2: Par e Impar\nEj3: Toggle\nEj4: Creación dinámica\nEj5: Validación básica" - }, - { - "objectID": "pages/Bloque3/DOM.html", - "href": "pages/Bloque3/DOM.html", - "title": "DOM", - "section": "", - "text": "El DOM (Document Object Model) es la representación en memoria que el navegador crea a partir del HTML.\n\nEl HTML es estático\nEl DOM es dinámico\nJavaScript interactúa con el DOM, no con el HTML original\n\n\nEl DOM es la página web viva dentro del navegador.", - "crumbs": [ - "Bloque III Interacción", - "Semana 6", - "DOM" - ] - }, - { - "objectID": "pages/Bloque3/DOM.html#qué-es-el-dom", - "href": "pages/Bloque3/DOM.html#qué-es-el-dom", - "title": "DOM", + "objectID": "pages/Bloque3/MAcss2.html", + "href": "pages/Bloque3/MAcss2.html", + "title": "MA: CSS Flex y CSS", "section": "", - "text": "El DOM (Document Object Model) es la representación en memoria que el navegador crea a partir del HTML.\n\nEl HTML es estático\nEl DOM es dinámico\nJavaScript interactúa con el DOM, no con el HTML original\n\n\nEl DOM es la página web viva dentro del navegador.", + "text": "Además de las propiedades estudiadas de CSS también hay algunas críticas que debido a la falta de tiempo no se han podido explicar como es el caso de display a continuación estos dos vídeos profundizan en los modos flex y grid formas diferentes de diseñar la estructura de la página", "crumbs": [ "Bloque III Interacción", "Semana 6", - "DOM" + "MA: CSS Flex y CSS" ] }, { - "objectID": "pages/Bloque3/DOM.html#el-dom-como-árbol", - "href": "pages/Bloque3/DOM.html#el-dom-como-árbol", - "title": "DOM", - "section": "El DOM como árbol", - "text": "El DOM como árbol\nEl DOM tiene estructura de árbol (grafo):\n\nCada etiqueta HTML es un nodo\nLos nodos tienen relaciones (padre, hijos, hermanos)\n\nEjemplo:\n<body>\n <h1>Título</h1>\n <button>Click</button>\n</body>\nRepresentación conceptual:\ndocument\n └─ body\n ├─ h1\n └─ button", - "crumbs": [ - "Bloque III Interacción", - "Semana 6", - "DOM" - ] + "objectID": "pages/Bloque3/reactI.html#sintaxis-jsx", + "href": "pages/Bloque3/reactI.html#sintaxis-jsx", + "title": "React I", + "section": "Sintaxis JSX", + "text": "Sintaxis JSX\n¿Qué es la sintaxis JSX?\n\nJSX (JavaScript XML) es una extensión de JavaScript utilizada en React.\n\nPermite escribir estructuras similares a HTML directamente dentro del código JavaScript.\n\nFacilita la creación y lectura de interfaces de usuario, integrando lógica y presentación.\n\nAunque su apariencia es HTML, JSX se transpila a JavaScript puro antes de ejecutarse en el navegador.\nForma cómoda de almacenar etiquetas html como variables de JS" }, { - "objectID": "pages/Bloque3/DOM.html#acceso-al-dom-desde-javascript", - "href": "pages/Bloque3/DOM.html#acceso-al-dom-desde-javascript", - "title": "DOM", - "section": "Acceso al DOM desde JavaScript", - "text": "Acceso al DOM desde JavaScript\nEl navegador nos proporciona el objeto global document, que permite:\n\nBuscar elementos\nLeer su contenido\nModificar la interfaz\n\ndocument\ndocument.body", - "crumbs": [ - "Bloque III Interacción", - "Semana 6", - "DOM" - ] + "objectID": "pages/Bloque3/reactI.html#react", + "href": "pages/Bloque3/reactI.html#react", + "title": "React I", + "section": "React", + "text": "React\nMotivación\nHasta el momento hemos trabajado únicamente con HTML5, el cual a pesar de ser muy eficaz, presenta el inconveniente de que no implementa ninguna clase de lógica. Es decir, si queremos repetir alguna estructura previamente definida deberemos copiarla y pegarla. Otro problema, de HTML puro es la complejidad que requiere el manejo del DOM, como ya se vio en la semana anterior.\nBajo este pretexto, introducimos el framework React diseñado por Meta." }, { - "objectID": "pages/Bloque3/DOM.html#selectores", - "href": "pages/Bloque3/DOM.html#selectores", - "title": "DOM", - "section": "Selectores", - "text": "Selectores\n\nPor ID\ndocument.getElementById(\"count\")\ndocument.querySelector(\"#count\")\n\n\nPor etiqueta\ndocument.querySelector(\"button\")\n\n\nPor clase\ndocument.querySelector(\".item\")\ndocument.querySelectorAll(\".item\")\nNotas: - querySelector devuelve el primer elemento - querySelectorAll devuelve una lista - Usan la misma sintaxis que CSS", - "crumbs": [ - "Bloque III Interacción", - "Semana 6", - "DOM" - ] + "objectID": "pages/Bloque3/reactI.html#creación-de-una-reactjs-app", + "href": "pages/Bloque3/reactI.html#creación-de-una-reactjs-app", + "title": "React I", + "section": "Creación de una ReactJS app", + "text": "Creación de una ReactJS app\nEl desarrollo de aplicaciones web modernas requiere coordinar múltiples elementos: estructura del proyecto, gestión de dependencias, compilación del código y ejecución en el navegador.\nUn framework de desarrollo proporciona un entorno de trabajo preconfigurado que organiza estos elementos y establece una forma estándar de trabajar." }, { - "objectID": "pages/Bloque3/DOM.html#leer-y-modificar-elementos", - "href": "pages/Bloque3/DOM.html#leer-y-modificar-elementos", - "title": "DOM", - "section": "Leer y modificar elementos", - "text": "Leer y modificar elementos\nelement.textContent\nelement.textContent = \"Nuevo texto\"\nelement.classList.add(\"active\")\nelement.classList.remove(\"active\")", + "objectID": "pages/Bloque3/ReactI.html", + "href": "pages/Bloque3/ReactI.html", + "title": "React I", + "section": "", + "text": "Contenido", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 7", + "React I" ] }, { - "objectID": "pages/Bloque3/DOM.html#eventos", - "href": "pages/Bloque3/DOM.html#eventos", - "title": "DOM", - "section": "Eventos", - "text": "Eventos\nEl DOM permite reaccionar a acciones del usuario mediante eventos.\nbutton.addEventListener(\"click\", () => {\n // código a ejecutar\n});\nFlujo típico:\nUsuario → Evento → JavaScript → DOM actualizado", + "objectID": "pages/Bloque3/ReactI.html#sintaxis-jsx", + "href": "pages/Bloque3/ReactI.html#sintaxis-jsx", + "title": "React I", + "section": "Sintaxis JSX", + "text": "Sintaxis JSX\n\n¿Qué es la sintaxis JSX?\n\nJSX (JavaScript XML) es una extensión de JavaScript utilizada en React.\n\nPermite escribir estructuras similares a HTML directamente dentro del código JavaScript.\n\nFacilita la creación y lectura de interfaces de usuario, integrando lógica y presentación.\n\nAunque su apariencia es HTML, JSX se transpila a JavaScript puro antes de ejecutarse en el navegador.\nForma cómoda de almacenar etiquetas html como variables de JS\n\n\n\n¿Qué nos ofrece la sintaxis JSX?\n\nAlmacenar una etiqueta como una variable\nconst title = <h1>Web del TC de SW</h1>;\n\nconst driveIndication = (drives)? <p>Puede conducir</p> : <p>No puede conducir</p>;\nDe esta forma la variable title se corresponde con una etiqueta que contiene el título. Sin embargo, como podemos podemos utilizar está etiqueta una vez la hemos definido como una variable.\n\n\nRenderizar etiquetas dentro de etiquetas\nconst title = <h1>Web del TC de SW</h1>;\n\nconst page = <div>{title}</div>\nDe esta forma estámos encapsulando la etiqueta h1 dentro del div.\n\n\nRenderizar con el map\nconst profeAsi= [[\"Rosa\", \"Macro I\"], [\"Gabriela\", \"FSO\"],[\"Yolanda\",\"LTP\"], [\"Ferrán\", \"EM\"], [\"Pepe\", \"TCO\"]];\n\n// Array de li Asignatura: nombre profesor\nconst itemsProfAsi = profeAsi.map(x => <li>{x[1]}: {x[0]}</li>);\n\nconst listaProfesoresAsignatura = <ul>{itemsProfAsi}</ul>;\n\n\nRenderizar con el map\nconst profeAsi= [[\"Rosa\", \"Macro I\"], [\"Gabriela\", \"FSO\"], [\"Yolanda\",\"LTP\"], [\"Ferrán\", \"EM\"], [\"Pepe\", \"TCO\"]];\n\nconst listaProfesoresAsignatura = <ul>\n{profeAsi.map((x,i) => <li key={i}>{x[1]}: {x[0]}</li>)}\n</ul>;", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 7", + "React I" ] }, { - "objectID": "pages/Bloque3/DOM.html#ejemplo-contador-con-botón", - "href": "pages/Bloque3/DOM.html#ejemplo-contador-con-botón", - "title": "DOM", - "section": "Ejemplo: contador con botón", - "text": "Ejemplo: contador con botón\n\nHTML\n<h1 id=\"count\">0</h1>\n<button id=\"btn\">Sumar 1</button>\n\n\nJavaScript\nlet count = 0;\n\nconst countEl = document.querySelector(\"#count\");\nconst btn = document.querySelector(\"#btn\");\n\nbtn.addEventListener(\"click\", () => {\n count++;\n countEl.textContent = count;\n});", + "objectID": "pages/Bloque3/ReactI.html#react", + "href": "pages/Bloque3/ReactI.html#react", + "title": "React I", + "section": "React", + "text": "React\n\nMotivación\nHasta el momento hemos trabajado únicamente con HTML5, el cual a pesar de ser muy eficaz, presenta el inconveniente de que no implementa ninguna clase de lógica. Es decir, si queremos repetir alguna estructura previamente definida deberemos copiarla y pegarla. Otro problema, de HTML puro es la complejidad que requiere el manejo del DOM, como ya se vio en la semana anterior.\nBajo este pretexto, introducimos el framework React diseñado por Meta.\n\n\nBases de React\nReact es un componente basado en la sintaxis JS y en la programación funcional introducida en ES6.\n\n\nComponente React\nLos componentes de React los definimos como unidades reutilizables y modulares que se implementan de esta forma: una función que devuelve un objeto de JSX\nfunction Saludo() {\n return <h1>Hola, mundo</h1>;\n}\nPodemos renderizar nuestro componente Saludo asumiendo que se comporta como una etiqueta html. Recordemos que no lo es.\n<main>\n <Saludo />\n</main>\nDentro de este componente podemos incluir lógica propia de JavaScript, de forma que al definir componente podemos dotarlo de lógica interna.\nfunction DivNúmeroAleatorio() {\n\n let n = Math.random();\n return <div className=\"n-random\">{n}</div>;\n}\n*Nótese que aunque JS utilice camelCase para el nombre de las funciones, con React utilizaremos PascalCase para definir los componentes puesto que a pesar de que se trata de funciones, trabajaremos con ellas como si fuesen clases.\n\n\nProps en React\nHasta ahora, los componentes definidos siempre devuelven el mismo contenido. Sin embargo, para que un componente sea realmente reutilizable, necesitamos poder pasarle información desde el exterior.\nEn React, esta información se transmite mediante props (properties).\nLas props se definen como los parámetros de entrada de un componente y permiten personalizar su comportamiento o su contenido sin modificar su definición interna.\n\nEjemplo 1: uso de props (forma explícita)\nfunction Saludo(props) {\n return <h1>Hola, {props.nombre}</h1>;\n}\nUso del componente:\n<Saludo nombre=\"Rosa\" />\n<Saludo nombre=\"Gabriela\" />\n\n\nEjemplo 2: props desestructuradas (sintaxis JavaScript)\nfunction Saludo({ nombre }) {\n return <h1>Hola, {nombre}</h1>;\n}\nUso del componente (idéntico al anterior):\n<Saludo nombre=\"Rosa\" />\n<Saludo nombre=\"Gabriela\" />\n\n\n\nEventos en React\nEn React, el manejo de eventos se basa en los eventos del DOM, pero utilizando una sintaxis propia de JSX y siguiendo el estilo de JavaScript.\n\nEjemplo básico de evento\nfunction BotonSaludo() {\n\n function manejarClick() {\n alert(\"Hola desde React\");\n }\n\n return (\n <button onClick={manejarClick}>\n Saludar\n </button>\n );\n}\n\n\nPaso de funciones como eventos\nLa función asociada al evento no se ejecuta al renderizar el componente, sino únicamente cuando ocurre el evento; es decir la pasamos como un ciudadano de primera clase.\n<button onClick={manejarClick}>Saludar</button>\nIncorrecto:\n<button onClick={manejarClick()}>Saludar</button>\n\n\nEventos más habituales en React\nReact soporta la mayoría de los eventos del DOM, adaptados a la sintaxis JSX. A continuación se listan los eventos más utilizados, clasificados por tipo.\n\nEventos de ratón\n\nonClick\nonDoubleClick\nonMouseEnter\nonMouseLeave\nonMouseMove\nonMouseDown\nonMouseUp\n\n\n\nEventos de teclado\n\nonKeyDown\nonKeyUp\nonKeyPress\n\n\n\nEventos de formularios\n\nonChange\nonSubmit\nonFocus\nonBlur\nonInput\nonReset\n\n\n\nEventos de carga y ciclo del elemento\n\nonLoad\nonError\n\n\n\nEventos de selección y portapapeles\n\nonSelect\nonCopy\nonCut\nonPaste\n\n\n\nEventos táctiles (dispositivos móviles)\n\nonTouchStart\nonTouchMove\nonTouchEnd\nonTouchCancel\n\n\n\n\n\nCiclo de vida de los componentes y renderizado en React\nEn React, los componentes no se renderizan directamente sobre el DOM real, sino que siguen un proceso intermedio que permite optimizar las actualizaciones de la interfaz.\nLa idea clave es que la interfaz se organiza como un árbol de componentes, análogo al árbol del DOM, pero a un nivel de abstracción superior.\n\nEl árbol de componentes\nCuando una aplicación React se ejecuta:\n\nCada componente genera otros componentes o elementos JSX.\nReact construye un árbol de componentes, donde:\n\nEl componente raíz suele ser App\nCada componente hijo ocupa una rama del árbol\n\n\nEste árbol de componentes se corresponde conceptualmente con el árbol del DOM, aunque no es el DOM real.\n\n\nProceso de renderizado\nEl proceso general es el siguiente:\n\nReact ejecuta un componente (función).\nEl componente devuelve JSX.\nEl JSX se transforma en una representación interna del árbol.\nReact compara este árbol con el anterior.\nSolo se actualizan en el DOM real los nodos que han cambiado.\n\nDe esta forma, React minimiza el acceso directo al DOM, que es una operación costosa.\n\n\nCiclo de vida (visión simplificada)\nDesde un punto de vista conceptual, un componente pasa por tres fases:\n\nMontaje\n\nEl componente se crea y se inserta en el DOM.\n\nActualización\n\nEl componente se vuelve a renderizar cuando cambian sus datos.\n\nDesmontaje\n\nEl componente se elimina del DOM.\n\n\nEn componentes funcionales modernos, este ciclo se gestiona de forma implícita mediante el renderizado y, más adelante, mediante hooks.\n\n\nRelación con el DOM\n\nEn JavaScript puro:\n\nSe modifica el DOM directamente.\n\nEn React:\n\nSe describe cómo debe ser la interfaz.\nReact decide el cuándo y el cómo modificar el DOM.\n\n\nEl desarrollador no recorre ni manipula el árbol del DOM, sino que trabaja sobre el árbol de componentes.", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 7", + "React I" ] }, { - "objectID": "pages/Bloque3/DOM.html#más-ejemplos", - "href": "pages/Bloque3/DOM.html#más-ejemplos", - "title": "DOM", - "section": "Más ejemplos", - "text": "Más ejemplos\nEj1: Show input\nEj2: Par e Impar\nEj3: Toggle\nEj4: Creación dinámica\nEj5: Validación básica", + "objectID": "pages/Bloque3/ReactI.html#creación-de-una-reactjs-app", + "href": "pages/Bloque3/ReactI.html#creación-de-una-reactjs-app", + "title": "React I", + "section": "Creación de una ReactJS app", + "text": "Creación de una ReactJS app\nEl desarrollo de aplicaciones web modernas requiere coordinar múltiples elementos: estructura del proyecto, gestión de dependencias, compilación del código y ejecución en el navegador.\nUn framework de desarrollo proporciona un entorno de trabajo preconfigurado que organiza estos elementos y establece una forma estándar de trabajar.\n\n¿Para qué sirve un framework?\nUn framework permite al desarrollador:\n\nEvitar configuraciones manuales complejas\nSeguir una estructura común de proyecto\nAutomatizar tareas repetitivas\nCentrarse en la lógica de la aplicación y no en la infraestructura\n\nEn lugar de partir de un proyecto vacío, el framework ofrece una base funcional sobre la que desarrollar.\n\n\nFramework y React\nReact se encarga de definir cómo se construye la interfaz, pero no gestiona por sí mismo:\n\nLa estructura de archivos\nEl arranque de la aplicación\nLa compilación del código\nEl servidor de desarrollo\n\nPor ello, React se apoya en un framework que orquesta el entorno de ejecución.\n\n\nCreación de la aplicación\nPara crear una nueva aplicación React utilizando un framework, se ejecuta el siguiente comando en la terminal:\nnpm create vite@latest\nEste comando genera:\n\nUna estructura inicial del proyecto\nLa configuración necesaria para trabajar con React\nUn entorno listo para el desarrollo", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 7", + "React I" ] }, { diff --git a/docs/site_libs/quarto-html/quarto-syntax-highlighting-dark-b758ccaa5987ceb1b75504551e579abf.css b/docs/site_libs/quarto-html/quarto-syntax-highlighting-dark-4d9afe2b8d18ee9fa5d0d57b5ed4214d.css old mode 100755 new mode 100644 similarity index 98% rename from docs/site_libs/quarto-html/quarto-syntax-highlighting-dark-b758ccaa5987ceb1b75504551e579abf.css rename to docs/site_libs/quarto-html/quarto-syntax-highlighting-dark-4d9afe2b8d18ee9fa5d0d57b5ed4214d.css index b21c946..9de3c1b --- a/docs/site_libs/quarto-html/quarto-syntax-highlighting-dark-b758ccaa5987ceb1b75504551e579abf.css +++ b/docs/site_libs/quarto-html/quarto-syntax-highlighting-dark-4d9afe2b8d18ee9fa5d0d57b5ed4214d.css @@ -216,4 +216,4 @@ code span.wa { content: "}} + +--- + +Con las `ref` podemos introducir los *uncontrolled fields* que nos permiten trabajar de otra forma con los formularios. + +{{< video https://www.youtube.com/watch?v=X2O7Wfmkuzw >}} + +Se prefiere la segunda implementación (la que no utiliza referencias) sobre la primera. \ No newline at end of file diff --git a/pages/Bloque3/PokeAPI-Example.zip b/pages/Bloque3/PokeAPI-Example.zip new file mode 100644 index 0000000000000000000000000000000000000000..430af25063879f9fdfd7228f1ad7a945fc6f2224 GIT binary patch literal 1267 zcmWIWW@Zs#U|`^2SiLYQ=2z*exVwxD411Uv7}yzP7#s@<^s?1n z3T_5QmKQ)3U?Miyw|};Qz~0~CKE;e-g43$9XD?ZGWy`9N+|?nrYrj2cbzI1JdsDlw z(v<)A3=^is>Y4H1JAUTIqP(?*ES`G%BW8==Q%`EDdSUZ!H5YeO`&;>-mV)L}GsT43 zS1tH?|NgU?~2@&{mPXAzRV>@mb#j(oY0jllAil?{jP=; zOoyG{S-oe!nBT~9;YzOWg+)ne6RyYpZpn+}KHT*n%gSQ*I?b7dP72Ixtsd%Fuob@0 z%{NG~SY72cZC#(swfZSW9$L}QTPN;0@%(#{(NCKrH|io<<6O?}YWfm8<;+>lXpsY~ zvU4q)j~Tz2YpfT0SDNYT6`q@H_bmeCLzLgDP4oSceY!v{?&}xd_>D1TWh=7IeK{{Z zS5H~LZO*>L=Vx9?eVW))S<|7dl4=Z%cCd)1$pc3p~S;yTACzlle9 z*3bL4o=z(iH!o|ru*gRvhRw0;8mH#shs!M!6TgI|yM-+H@!5A$i&c{rM?>z$7s(1= z=RGqtyj7{E%bg-M+t}GAMgP5#@scMUnau`F6juCvN2X@**vhDQg- zqf-4fi+|h;cUrbIGqvvS|9iP@JEpBGd_UFh$qnvq$6eub56EsZ-?aV@i*WKed5`Tu z$F6;fD3SZ26nb29hx0|F3jQqb1u`=(Pq$uv%AqD<#ZJqQ1`U1JVjLc`%B?XCYq4go z2<=d{JImaPNF1&*_l!4_;bwH6^;%FZ8?k zjdxG)Ri(LW+d^0UbDHG+yll_w!W-sQwU;+p)y0JW6MB{+cUtJJo0Ul5-lz@9BFnm% zWdddUMB3-uPrWWM$M?}G<#Vx_qJ@Wl`k3xrGUH^ipQ+BSKUbSlKiHQm9LO$y5qsuG z!}R|Q0p5&Ea?H324+&tQ!oUDbEeuN