1. Prima di iniziare
Angular Signals introduce tre primitive reattive in Angular, che conosci e ami, semplificando lo sviluppo e aiutandoti a creare app più veloci per impostazione predefinita.
Cosa creerai
- Scopri le tre primitive reattive introdotte con Angular Signals:
signal()
,computed()
eeffect()
. - Utilizza Angular Signals per potenziare un gioco di crittografia Angular. I sistemi di crittografia sono sistemi per criptare e decriptare i dati. In questo gioco, gli utenti possono decodificare un messaggio segreto trascinando indizi per risolvere la crittografia, personalizzare il messaggio e condividere l'URL per inviare messaggi segreti agli amici.
Prerequisiti
- Conoscenza di Angular e TypeScript
- Consigliato: guarda Rethinking Reactivity with Signals per saperne di più sulla libreria Angular Signals
2. Ottieni il codice
Tutto ciò che ti serve per questo progetto si trova in un Stackblitz. Stackblitz è il metodo consigliato per svolgere questo codelab. In alternativa, clona il codice e aprilo nel tuo ambiente di sviluppo preferito.
Apri Stackblitz ed esegui l'app.
Per iniziare, apri il link a Stackblitz nel tuo browser web preferito:
- Apri una nuova scheda del browser e vai a https://stackblitz.com/edit/io-signals-codelab-starter?file=src%2Fcipher%2Fservice.cipher.ts,src%2Fsecret-message%2Fservice.message.ts&service.massage.ts
- Crea un fork di Stackblitz per creare la tua area di lavoro modificabile. Stackblitz dovrebbe eseguire automaticamente l'app ed è tutto pronto per iniziare.
Alternativa: clona il repository e pubblica l'app
L'utilizzo di VSCode o di un IDE locale è un metodo alternativo per svolgere questo codelab:
- Apri una nuova scheda del browser e vai a https://github.com/angular/codelabs/tree/signals-get-started.
- Crea un fork e clona il repository, quindi utilizza il comando
cd codelabs/
per spostarti nel repository. - Controlla il ramo del codice di avvio con il comando
git checkout signals-get-started
. - Apri il codice in VSCode o nel tuo IDE preferito.
- Per installare le dipendenze necessarie per l'esecuzione del server, utilizza il comando
npm install
. - Per eseguire il server, utilizza il comando
ng serve
. - Apri una scheda del browser all'indirizzo http://localhost:4200.
3. Stabilire un valore di riferimento
Il tuo punto di partenza è un gioco Angular Cipher, ma non funziona ancora. Angular Signals supporterà la funzionalità del gioco.
Per iniziare, esamina la versione finale di ciò che stai creando: Angular Signals Cypher.
- Visualizza il messaggio codificato sullo schermo.
- Trascina un pulsante con una lettera nel tastierino per cercare di risolvere il codice e decodificare il messaggio segreto.
- In caso di esito positivo, osserva come il messaggio viene aggiornato per decodificare una parte maggiore del messaggio segreto.
- Fai clic su Personalizza per modificare il mittente e il messaggio, quindi fai clic su Crea e copia URL per visualizzare i valori sullo schermo e la modifica dell'URL.
- Bonus: copia e incolla l'URL in una nuova scheda oppure condividilo con un amico per vedere come il mittente e il messaggio sono memorizzati nell'URL.
4. Definisci il primo indicatore()
Un indicatore è un valore che può indicare ad Angular quando cambia. Alcuni indicatori possono essere modificati direttamente, mentre altri calcolano i loro valori a partire dai valori di altri indicatori. Insieme, i segnali creano un grafo diretto di dipendenze che modella il flusso dei dati nella tua app.
Angular può utilizzare le notifiche degli indicatori per sapere quali componenti devono essere rilevati dalle modifiche o per eseguire le funzioni effect da te definite.
Converti superSecretMessage
in signal()
superSecretMessage
è un valore in MessageService
che definisce il messaggio segreto decodificato dal giocatore. Attualmente, il valore non comunica all'app le modifiche apportate, pertanto il pulsante Personalizza non funziona. Puoi risolvere il problema con un indicatore.
Se imposti un segnale superSecretMessage
, puoi inviare notifiche alle parti dell'app che dipendono dalla conoscenza della modifica del messaggio. Quando personalizzi il messaggio in una finestra di dialogo, imposti l'indicatore per aggiornare il resto dell'app con il nuovo messaggio.
Per definire il primo indicatore, esegui i seguenti passaggi sotto il commento TODO(1): Define your first signal()
in ogni file:
- Nel file
service.message.ts
, utilizza la raccolta degli indicatori per rendere reattivosuperSecretMessage
:
src/app/secret-message/service.message.ts
superSecretMessage = signal(
'Angular Signals are in developer preview in v16 today!'
);
In questo modo ti viene chiesto automaticamente di importare signal
da @angular/core
. Se aggiorni la pagina, probabilmente riscontrerai errori nei punti in cui in precedenza facevi riferimento a superSecretMessage
. Questo perché hai modificato il tipo di superSecretMessage
da string
a SettableSignal<string>
. Puoi risolvere il problema modificando tutti i riferimenti di superSecretMessage
in modo che utilizzi l'API Signals. Ovunque tu legga il valore, chiama il getter dell'indicatore superSecretMessage()
. Ogni volta che scrivi il valore, utilizza l'API .set
su SettableSignal
per impostare il nuovo valore per il messaggio.
- Nei file
secret-message.ts
eservice.message.ts
, aggiorna tutti i riferimenti disuperSecretMessage
insuperSecretMessage()
:
src/app/secret-message/secret-message.ts
// Before
this.messages.superSecretMessage
this.messages.superSecretMessage = message;
// After
this.messages.superSecretMessage()
this.messages.superSecretMessage.set(message);
src/app/secret-message/service.message.ts
// Before
this.superSecretMessage
// After
this.superSecretMessage()
Esplora gli altri due indicatori
- Tieni presente che nella tua app sono presenti altri due indicatori:
src/app/cipher/service.cipher.ts
cipher = signal(this.createNewCipherKey());
decodedCipher = signal<CipherKey[]>([]);
CipherService
definisce un segnale cipher
, una mappatura generata in modo casuale di coppie chiave-valore di una lettera dell'alfabeto a una nuova lettera cipher
. Lo utilizzi per criptare il messaggio e determinare se il giocatore trova una corrispondenza sulla tastiera.
Hai anche un indicatore decodedCipher
delle coppie chiave-valore decodificate correttamente che aggiungerai man mano che il giocatore risolve il codice.
Un attributo unico e potente del design della libreria Signals di Angular è che puoi introdurre la reattività ovunque. Dopo aver definito gli indicatori una volta nei servizi dell'app, puoi utilizzarli in un modello, in componenti, in pipe, in altri servizi o ovunque tu possa scrivere codice dell'applicazione. Non sono limitati o vincolati all'ambito di un componente.
Verificare le modifiche
- Devi completare un altro passaggio prima che l'app funzioni. Per il momento, prova ad aggiungere un
console.log()
in parti diverse dell'app per vedere come viene impostato il nuovosuperSecretMessage
.
5. Definisci la tua prima funzione computed()
In molte situazioni potresti ricavare uno stato da valori esistenti. È meglio che lo stato derivato venga aggiornato quando cambia il valore dipendente.
Con computed()
, puoi esprimere in modo dichiarativo un indicatore che ricava il proprio valore da altri indicatori.
Converti solvedMessage
in computed()
solvedMessage
converte il valore secretMessage
da codificato a decodificato utilizzando il segnale decodedCipher
.
Questo è davvero fantastico perché puoi vedere che stai ricavando un calcolo basato su un altro calcolato, quindi ogni volta che un segnale all'interno di quel contesto reattivo mappato cambia, le dipendenze vengono notificate.
Al momento, solvedMessage
non viene aggiornato quando modifichi secretMessage
, decodedCipher
o superSecretMessage
. Di conseguenza, non visualizzi aggiornamenti sullo schermo quando il giocatore risolve il codice.
Se imposti solvedMessage
come calcolato, crei un contesto reattivo in modo che, quando aggiorni il messaggio o risolvi la crittografia, tu possa dedurre l'aggiornamento dello stato dalle dipendenze monitorate.
Per convertire solvedMessage
in computed()
, esegui i seguenti passaggi sotto il commento TODO(2): Define your first computed()
in ogni file:
- Nel file
service.message.ts
, utilizza la libreria Signals per renderesolvedMessage
reattivo:
src/app/secret-message/service.message.ts
solvedMessage = computed(() =>
this.translateMessage(
this.secretMessage(),
this.cipher.decodedCipher()
)
);
In questo modo ti viene chiesto automaticamente di importare computed
da @angular/core
. Se aggiorni la pagina, probabilmente riscontrerai errori nei punti in cui in precedenza facevi riferimento a solvedMessage
. Questo perché hai modificato il tipo di superSecretMessage
da string
a Signal<string>
, una funzione. Per risolvere il problema, puoi sostituire tutti i riferimenti a solvedMessage
con solvedMessage()
.
- Nel file
secret-message.ts
, aggiorna tutti i riferimenti disolvedMessage
insolvedMessage()
:
src/app/secret-message/secret-message.ts
// Before
<span *ngFor="let char of this.messages.solvedMessage.split(''); index as i;" [class.unsolved]="this.messages.solvedMessage[i] !== this.messages.superSecretMessage()[i]" >{{ char }}</span>
// After
<span *ngFor="let char of this.messages.solvedMessage().split(''); index as i;" [class.unsolved]="this.messages.solvedMessage()[i] !== this.messages.superSecretMessage()[i]" >{{ char }}</span>
Tieni presente che, a differenza di superSecretMessage
, solvedMessage
non è un SettableSignal
, quindi non puoi modificarne direttamente il valore. Il suo valore viene mantenuto aggiornato ogni volta che viene aggiornato uno dei suoi indicatori di dipendenza (secretMessage
e decodedCipher
).
Esplora le altre due computed()
funzioni
- Tieni presente che nella tua app sono presenti altri due valori calcolati:
src/app/secret-message/service.message.ts
secretMessage = computed(() =>
this.translateMessage(
this.superSecretMessage(),
this.cipher.cipher()
)
);
src/app/cipher/service.cipher.ts
unsolvedAlphabet = computed(() =>
ALPHABET.filter(
(letter) => !this.decodedCipher().find((guess) => guess.value === letter)
)
);
Il MessageService
definisce un secretMessage
calcolato, il superSecretMessage
codificato dal cipher
che i player devono risolvere.
CipherService
definisce un unsolvedAlphabet
calcolato, un elenco di tutte le lettere che il giocatore non ha risolto, che deriva dall'elenco delle chiavi di crittografia risolte in decodedCipher
.
Verificare le modifiche
Ora che superSecretMessage
è un indicatore e solvedMessage
è un valore calcolato, l'app dovrebbe funzionare. Prova le funzionalità del gioco:
- Trascina un
LetterGuessComponent
in unLetterKeyComponent
diCipherComponent
per risolvere la crittografia e decodificare il messaggio segreto. - Guarda come si aggiorna
SecretMessageComponent
man mano che decodifichi altro del messaggio segreto. - Fai clic su Personalizza per modificare il mittente e il messaggio, quindi fai clic su Crea e copia URL per visualizzare i valori sullo schermo e la modifica dell'URL.
- Bonus: copia e incolla l'URL in una nuova scheda oppure condividilo con un amico per vedere come il mittente e il messaggio sono memorizzati nell'URL.
6. Aggiungi il tuo primo effetto()
A volte potresti voler che si verifichi qualcosa quando un indicatore ha un nuovo valore. Con effect()
, puoi pianificare ed eseguire una funzione di gestore in risposta alla modifica degli indicatori.
Aggiungere coriandoli quando la crittografia è risolta
Ora che l'app è funzionante, puoi aggiungere un tocco di divertimento aggiungendo dei coriandoli quando la crittografia è risolta e il messaggio segreto è stato decodificato.
Per aggiungere coriandoli, procedi nel seguente modo sotto il commento TODO(3): Add your first effect()
:
- Nel file
cipher.ts
, pianifica un effetto per aggiungere coriandoli quando il messaggio viene decodificato:
src/app/cipher/cipher.ts
import * as confetti from 'canvas-confetti';
ngOnInit(): void {
...
effect(() => {
if (this.messages.superSecretMessage() === this.messages.solvedMessage()) {
var confettiCanvas = document.getElementById('confetti-canvas');
confetti.create()(confettiCanvas, { particleCount: 100 });
}
});
}
Nota come questo effetto dipende da un indicatore e da un valore calcolato: this.messages.superSecretMessage()
e this.messages.solvedMessage()
.
L'effetto ti aiuta a pianificare la funzione dei coriandoli all'interno di un contesto reattivo per monitorare e rivalutare quando le sue dipendenze vengono aggiornate.
Verificare le modifiche
- Prova a decifrare il codice (suggerimento: puoi cambiare il messaggio con un messaggio breve per eseguire il test più velocemente). Uno scoppiettante coriandoli si congratula con te per il tuo primo
effect()
!
7. Complimenti!
Il tuo codice Angular è ora pronto per decodificare e condividere messaggi segreti. Hai un messaggio per il team di Angular? Tagga i nostri social media su @Angular per consentirci di decodificarli. 🎉
Ora nella cassetta degli attrezzi di Angular sono disponibili tre nuove primitive reattive per semplificare lo sviluppo e creare app più veloci per impostazione predefinita.
Scopri di più
Dai un'occhiata a questi codelab:
Leggi questi materiali:
- Angular.io
- Ripensare la reattività con gli indicatori (Google I/O 2023)
- Novità di Angular (Google I/O 2023)