L'última lliçó del mòdul 9 ho va anunciar amb aquestes paraules exactes: "queda una única lliçó, l'última del curs: 'Projecte: Construint TaskFlow', on no es presenta cap concepte nou, sinó que es recorre l'aplicació de principi a fi". Aquesta "única lliçó" és, en realitat, aquest mòdul complet, dividit en quatre parts per comoditat de lectura, però pensat com una sola unitat narrativa: el projecte final. Aquesta primera part encara no escriu cap component; traça el mapa complet de TaskFlow tal com ha quedat després de nou mòduls —el seu arbre de components, com viatgen les dades entre ells, i l'estructura de carpetes final del projecte— perquè les tres lliçons següents tinguin un plànol clar sobre el qual construir, en lloc de reconstruir aquesta imatge de conjunt sobre la marxa.
Contingut
- Què és aquest mòdul i què no és
- L'arbre de components de TaskFlow, complet
- Responsabilitat d'una línia, per component
- Flux de dades: propietats cap avall
- Flux de dades: esdeveniments cap amunt
- L'excepció deliberada: el context de filtre
- Estructura de carpetes final del projecte
- De la carpeta a la lliçó: on es va explicar cada peça
- Cap a la construcció dels components
- Què és aquest mòdul i què no és
Convé fixar això abans d'escriure una sola línia de codi: aquest mòdul no introdueix cap concepte de Lit que no s'hagi explicat ja entre els mòduls 1 i 9. Plantilles, propietats reactives, estils amb Shadow DOM, esdeveniments personalitzats, cicle de vida, controladors, mixins, directives, context compartit, integració amb la resta de l'ecosistema i bones pràctiques: tot això ja està cobert. El que sí que falta, i és exactament l'objectiu de les quatre lliçons d'aquest mòdul, és veure-ho tot unit, com un únic projecte coherent, en lloc d'una successió de fragments de codi repartits entre trenta-sis lliçons diferents, cadascuna centrada en la tècnica que li corresponia explicar en el seu moment.
Aquesta primera lliçó es limita a la planificació: l'arbre de components final, el flux de dades que els connecta, i l'estructura de carpetes. Les lliçons 10-02 i 10-03 escriuen el codi complet de cada component i cada peça d'infraestructura compartida, i la 10-04 tanca amb proves, empaquetatge i el propi tancament del curs.
- L'arbre de components de TaskFlow, complet
TaskFlow ha crescut, al llarg del curs, fins a convertir-se en cinc components personalitzats, organitzats en un arbre de quatre nivells de profunditat:
<task-board> (arrel de l'aplicació)
├── <task-filter> (germà de <task-list>)
└── <task-list>
└── <task-card> (una per tasca, repetida amb repeat + key)
└── <user-avatar>Cap component d'aquest arbre és nou: <task-board> va aparèixer al mòdul 5 (05-04) com a ancestre comú de <task-list>; <user-avatar> al mòdul 4 (04-04), com a fill de <task-card>; i <task-filter>, esmentat des del propi mòdul 5 sense implementar, no va cobrar vida real fins al mòdul 7 (07-04), de la mà de @lit/context. L'únic que aporta aquesta lliçó és dibuixar, per fi, l'arbre complet d'una sola vegada, una cosa que cap lliçó anterior necessitava fer perquè cadascuna se centrava en la peça que estava construint en aquell moment.
- Responsabilitat d'una línia, per component
Cada component de TaskFlow té una responsabilitat que es pot resumir en una sola frase, sense necessitat d'enumerar tots els detalls de la seva implementació:
| Component | Responsabilitat en una línia |
|---|---|
<task-board> |
Orquestrador arrel: manté l'array tareas, publica el context de filtre, i gestiona la càrrega inicial i els canvis d'estat que pugen des dels seus descendents. |
<task-filter> |
Ofereix els controls de cerca per text i per estat, i escriu els canvis directament al context de filtre compartit. |
<task-list> |
Consumeix el context de filtre, decideix quines tasques compleixen el criteri actiu, i les renderitza de manera eficient amb repeat i una clau estable. |
<task-card> |
Mostra les dades d'una única tasca, permet canviar-ne l'estat, i avisa visualment quan aquesta tasca està a prop de la seva data límit. |
<user-avatar> |
Mostra la persona assignada a una tasca, amb una imatge real o amb les seves inicials com a alternativa, mitjançant contingut distribuït. |
Aquesta taula, encara que sembli trivial, és la prova que la descomposició de TaskFlow en cinc peces, feta al llarg del curs, segueix el criteri explicat a la lliçó "Patrons i Antipatrons Comuns" (09-04, apartat 6): cada component canvia per un motiu diferent del dels altres, i cap no necessita la conjunció "i" per descriure's.
- Flux de dades: propietats cap avall
El primer eix de comunicació de TaskFlow, establert des del mòdul 3 i perfeccionat al mòdul 5, és el flux de propietats reactives d'un component cap als seus fills directes a la plantilla:
| Des de | Fins a | Què baixa |
|---|---|---|
<task-board> |
<task-list> |
.tareas (l'array complet, ja filtrat no; sense filtrar: el filtratge passa dins de <task-list>, a partir del context) |
<task-list> |
<task-card> |
.titulo, .estado, .prioridad, .urgente, .fechaLimite, asignado-a, asignado-imagen, una instància per cada tasca de l'array, amb tarea.id com a clau de repeat |
<task-card> |
<user-avatar> |
L'atribut nombre, i opcionalment una imatge distribuïda mitjançant <slot> en lloc d'una propietat |
Cap fila d'aquesta taula és nova: la primera es va establir a la lliçó "Patrons de Comunicació entre Components Germans" (05-04), la segona a "Comunicació de Pare a Fill amb Propietats" (05-03) i es va refinar amb repeat a "Context Compartit amb @lit/context" (07-04), i la tercera a "Slots i Estilització de Contingut Distribuït" (04-04). El que aporta aquesta lliçó és, de nou, veure-les juntes com un únic flux descendent continu, des de l'arrel de l'arbre fins a la seva fulla més profunda.
- Flux de dades: esdeveniments cap amunt
El segon eix, simètric a l'anterior, és el dels esdeveniments personalitzats que pugen des d'on passa una interacció fins a qui té l'autoritat per decidir què fer-ne:
<task-card> --tarea-cambiada (detail: { nuevoEstado })-->
<task-list> --tarea-cambiada (detail: { idTarea, nuevoEstado })-->
<task-board>Aquest reenviament en dos salts, amb l'idTarea afegit explícitament en el segon esdeveniment perquè <task-board> no té accés al tancament sobre tarea.id que sí que té <task-list>, es va establir íntegrament a les lliçons "Esdeveniments Personalitzats: Comunicació de Fill a Pare" (05-02) i "Patrons de Comunicació entre Components Germans" (05-04). <task-board> és, en tot moment, l'únic component de TaskFlow que modifica realment l'array tareas; tots els altres es limiten a anunciar fets ocorreguts sobre ells mateixos, mai a modificar directament l'estat d'un ancestre.
- L'excepció deliberada: el context de filtre
Els dos eixos anteriors —propietats cap avall, esdeveniments cap amunt— cobreixen tota la comunicació de TaskFlow excepte una relació: la que connecta <task-filter> amb <task-list>, dos components germans sense relació directa de pare a fill. Com es va explicar a la lliçó "Context Compartit amb @lit/context" (07-04), resoldre aquesta relació mitjançant el patró dels dos apartats anteriors obligaria <task-board> a reenviar manualment, a cada tecla premuda al filtre, una propietat cap a <task-list> que el mateix <task-board> no necessita per a res per si mateix.
<task-board> (ContextProvider de filtroContext)
↑↓ ↑↓
<task-filter> <task-list>
(ContextConsumer, escriu) (ContextConsumer, llegeix)<task-board> publica el context una única vegada, al seu constructor; <task-filter> el consumeix per llegir i per escriure (a través de la funció actualizar inclosa en el propi valor del context); <task-list> el consumeix només per llegir, i decideix amb aquest valor quines tasques compleixen el filtre abans de passar-les, ja com a propietat normal, cap a cada <task-card>. Cap dels dos germans coneix l'altre en cap moment: tots dos parlen únicament amb el context que <task-board> publica, exactament el mecanisme estudiat al mòdul 7.
- Estructura de carpetes final del projecte
Amb l'arbre de components i els dos eixos de comunicació ja traçats, l'estructura de carpetes de TaskFlow, tal com queda al final del curs, organitza cada peça segons el tipus de responsabilitat que compleix, no segons el mòdul en què es va introduir:
taskflow/
├── index.html
├── package.json
├── vite.config.js
├── web-test-runner.config.js
├── src/
│ ├── components/
│ │ ├── task-board.js
│ │ ├── task-filter.js
│ │ ├── task-list.js
│ │ ├── task-card.js
│ │ └── user-avatar.js
│ ├── controllers/
│ │ └── contador-tiempo-restante-controller.js
│ ├── mixins/
│ │ └── con-estado-carga.js
│ ├── context/
│ │ └── filtro-context.js
│ ├── directives/
│ │ └── resaltar-si-urgente.js
│ ├── services/
│ │ └── tareas-service.js
│ └── styles/
│ └── shared-styles.js
└── test/
├── task-card.test.js
└── task-filter.test.jssrc/components/ reuneix els cinc elements personalitzats de l'arbre de l'apartat 2; src/controllers/ i src/mixins/ separen, seguint el criteri de la lliçó "Mixins i Composició de Comportament" (06-04), la lògica amb estat propi i cicle de vida (ContadorTiempoRestanteController) de la lògica que s'integra directament a l'API pública d'un component (ConEstadoCarga); src/context/ conté la clau de context compartida entre <task-board>, <task-filter> i <task-list>; src/directives/ guarda la directiva personalitzada resaltarSiUrgente; src/services/ aïlla la simulació de càrrega de dades externa a qualsevol component concret; i src/styles/ manté els estils compartits entre diversos components. test/ reuneix la bateria de proves construïda al mòdul 9.
- De la carpeta a la lliçó: on es va explicar cada peça
Aquesta taula final serveix d'índex invers: donat un fitxer de l'estructura anterior, indica en quina lliçó del curs es va explicar per primera vegada la tècnica que aquest fitxer aplica, útil com a referència ràpida durant les tres lliçons següents d'aquest mòdul.
| Fitxer o carpeta | Lliçó on es va explicar la tècnica |
|---|---|
components/task-board.js (orquestrador, context, càrrega amb until) |
05-04, 06-04, 07-03, 07-04 |
components/task-filter.js (context, accessibilitat) |
07-04, 09-02 |
components/task-list.js (repeat, context consumidor) |
02-04, 07-04, 09-03 |
components/task-card.js (propietats, esdeveniments, controlador, directiva, accessibilitat) |
03-01 a 03-04, 05-02, 06-03, 07-02, 09-02 |
components/user-avatar.js (slots, variables CSS) |
04-03, 04-04 |
controllers/contador-tiempo-restante-controller.js |
06-03 |
mixins/con-estado-carga.js |
06-04 |
context/filtro-context.js |
07-04 |
directives/resaltar-si-urgente.js |
07-02 |
services/tareas-service.js |
07-03 |
styles/shared-styles.js |
04-02 |
test/*.test.js |
09-01, 09-02 |
- Cap a la construcció dels components
Amb l'arbre, els dos eixos de comunicació, l'excepció del context i l'estructura de carpetes ja fixats, aquesta lliçó ha complert la seva funció de mapa. Les tres lliçons següents es limiten a recórrer-lo: primer els components que mostren dades, després els que orquestren l'estat, i finalment les proves, l'empaquetatge i el tancament del curs.
Errors Comuns i Consells
- Organitzar les carpetes per mòdul del curs en lloc de per tipus de responsabilitat: una estructura com
modulo-06/,modulo-07/reflectiria l'ordre en què es va aprendre cada tècnica, no com s'organitza un projecte real;components/,controllers/,mixins/,context/agrupen el codi segons el seu paper dins de l'aplicació, que és el criteri que sobreviu un cop acabat el curs. - Oblidar que el context de filtre és una excepció, no la regla general: com s'ha explicat a l'apartat 6, la immensa majoria de la comunicació de TaskFlow segueix el patró de propietats cap avall i esdeveniments cap amunt;
@lit/contextes reserva per a l'únic cas —germans sense relació directa— que aquest patró no resol bé per si sol. - Pensar que
<task-board>coneix l'estructura interna de<task-card>:<task-board>només coneix<task-list>(el seu fill directe) i, mitjançant el context,<task-filter>; mai no ha tingut, ni necessita tenir, cap referència directa a una<task-card>concreta, gràcies al reenviament d'esdeveniments explicat a l'apartat 5. - Esperar que aquesta lliçó contingui codi executable: deliberadament, no en conté; és un mapa per a les tres lliçons següents, no una implementació.
Exercicis
- Sense mirar les lliçons anteriors, dibuixa de memòria l'arbre de components de l'apartat 2 i, al costat de cada fletxa, escriu si aquesta relació es resol amb una propietat, amb un esdeveniment, o amb el context de filtre. Comprova després el resultat contra els apartats 4, 5 i 6.
- Explica, basant-te en l'apartat 5, per què
<task-list>necessita afegiridTareaaldetailde l'esdevenimenttarea-cambiadaque reenvia, quan<task-card>, l'origen de l'esdeveniment, mai no va incloure aquesta dada en el seu. - Un company d'equip proposa moure
contador-tiempo-restante-controller.jsasrc/components/, argumentant que només l'utilitza<task-card>. Explica, basant-te en l'apartat 7 i en el criteri de la lliçó "Mixins i Composició de Comportament" (06-04), per quèsrc/controllers/continua sent la ubicació més adequada tot i que, de moment, només un component l'utilitzi.
Solucions
- L'arbre correcte és el de l'apartat 2:
<task-board>amb dos fills,<task-filter>i<task-list>;<task-list>amb una<task-card>per cada tasca; cada<task-card>amb un<user-avatar>. Les relacions són:<task-board>→<task-list>(propietat.tareas),<task-list>→<task-card>(propietats per tasca),<task-card>→<user-avatar>(atribut i contingut distribuït),<task-card>→<task-list>→<task-board>(esdevenimenttarea-cambiadaen dos salts), i<task-board>↔<task-filter>/<task-board>↔<task-list>(context de filtre, en totes dues direccions per a<task-filter>, només lectura per a<task-list>). <task-card>no coneix el concepte d'"identificador de tasca": és un component aïllat que només sap de si mateix, i l'esdeveniment que despatxa (tarea-cambiada, amb nomésnuevoEstadoal seudetail) reflecteix exactament aquesta ignorància deliberada.<task-list>, en canvi, sí que coneix l'estructura de l'arraytareas(gràcies al tancament detarea.idcapturat en recórrer l'array ambrepeat), i és l'única que pot afegir aquesta informació abans que l'esdeveniment continuï pujant; si no l'afegís,<task-board>, que no té cap tancament sobre quina targeta concreta va disparar l'esdeveniment, no podria saber quin element de l'array ha d'actualitzar.ContadorTiempoRestanteControllerno és, en si mateix, part de l'API pública ni de la plantilla de cap component: és un objecte amb estat propi i cicle de vida, pensat deliberadament (com es va explicar a 06-03) per ser reutilitzable per qualsevol host futur que exposi una propietatfechaLimite, no només per<task-card>. Col·locar-lo asrc/components/suggeriria que és, ell mateix, un element personalitzat registrat ambcustomElements.define, cosa que no és el cas;src/controllers/reflecteix correctament la seva naturalesa —una peça de comportament reutilitzable, desacoblada de qualsevol component concret— independentment de quants hosts l'utilitzin avui.
Conclusió
Aquesta lliçó ha traçat el mapa complet de TaskFlow sense escriure cap component nou: l'arbre de cinc components amb la seva responsabilitat d'una línia cadascun, els dos eixos de comunicació —propietats cap avall, esdeveniments cap amunt— que resolen quasi tota l'aplicació, l'excepció deliberada del context de filtre per a l'única parella de germans sense relació directa, i l'estructura de carpetes final que organitza cada peça segons el seu paper, no segons el mòdul en què es va aprendre.
Amb aquest mapa ja traçat, la lliçó següent, "Construint els Components Principals", comença a omplir-lo de veritat: el codi complet i consolidat de <user-avatar>, <task-card> i <task-filter>, unint en un sol fitxer per component totes les peces que aquest mateix curs va anar afegint per parts, mòdul a mòdul.
Curs de Lit
Mòdul 1: Introducció a Lit i Web Components
- Què són els Web Components i per què Lit?
- Configuració de l'Entorn de Desenvolupament
- El Teu Primer Component Lit
- Anatomia d'un Component Lit
Mòdul 2: Plantilles Reactives i Renderitzat
- El Motor de Plantilles de Lit
- Expressions i Interpolació en Plantilles
- Renderitzat Condicional
- Renderitzat de Llistes
- El Cicle de Renderitzat
Mòdul 3: Propietats i Estat Reactiu
- Propietats Reactives
- Estat Intern amb @state
- Tipus de Propietats i Conversors Personalitzats
- Atributs vs Propietats i Reflexió
Mòdul 4: Estils en Components Lit
- CSS Encapsulat amb Shadow DOM
- Estils Compartits entre Components
- Variables CSS Personalitzades i Theming
- Slots i Estilitzat de Contingut Distribuït
Mòdul 5: Esdeveniments i Comunicació entre Components
- Gestió d'Esdeveniments DOM en Plantilles
- Esdeveniments Personalitzats: Comunicació de Fill a Pare
- Comunicació de Pare a Fill amb Propietats
- Patrons de Comunicació entre Components Germans
Mòdul 6: Cicle de Vida i Comportament Avançat
- Callbacks del Cicle de Vida
- Hooks Reactius: willUpdate, updated i firstUpdated
- Controladors Reactius
- Mixins i Composició de Comportament
Mòdul 7: Directives i Funcionalitats Avançades de Plantilles
- Directives Incorporades: classMap, styleMap i ifDefined
- Directives Personalitzades
- Renderitzat Asíncron amb until
- Context Compartit amb @lit/context
Mòdul 8: Integració, Interoperabilitat i Desplegament
- Utilitzar Components Lit en HTML Pla
- Integrar Lit amb React, Vue i Angular
- Renderitzat al Servidor amb @lit-labs/ssr
- Empaquetatge, Publicació i TypeScript
Mòdul 9: Proves i Bones Pràctiques
- Proves Unitàries amb Web Test Runner
- Accessibilitat en Web Components
- Rendiment i Optimització
- Patrons i Antipatrons Comuns
