1. Zanim zaczniesz

Sygnały Angulara wprowadzają 3 reaktywne elementy pierwotne do znanego i lubianego Angulara, upraszczając proces tworzenia i pomagając domyślnie budować szybsze aplikacje.
Co utworzysz
- Poznasz 3 reaktywne elementy pierwotne wprowadzone w Angular Signals:
signal(),computed()ieffect(). - Użyj sygnałów Angulara, aby stworzyć grę Angular Cipher. Szyfry to systemy szyfrowania i odszyfrowywania danych. W tej grze użytkownicy mogą dekodować tajną wiadomość, przeciągając i upuszczając wskazówki, aby rozwiązać mechanizm szyfrowania. Mogą też dostosować wiadomość i udostępnić adres URL, aby wysyłać tajne wiadomości do znajomych.

Wymagania wstępne
- Znajomość Angulara i Typescriptu
- Zalecane: obejrzyj film Rethinking Reactivity with Signals, aby dowiedzieć się więcej o bibliotece Angular Signals.
2. Pobierz kod
Wszystko, czego potrzebujesz do tego projektu, znajdziesz w Stackblitz. Stackblitz to zalecana metoda pracy z tym ćwiczeniem z programowania. Możesz też sklonować kod i otworzyć go w ulubionym środowisku programistycznym.
Otwórz Stackblitz i uruchom aplikację
Aby rozpocząć, otwórz link do Stackblitz w ulubionej przeglądarce:
- Otwórz nową kartę przeglądarki i wejdź na stronę https://stackblitz.com/edit/io-signals-codelab-starter?file=src%2Fcipher%2Fservice.cipher.ts,src%2Fsecret-message%2Fservice.message.ts&service.massage.ts
- Skopiuj StackBlitz, aby utworzyć własny obszar roboczy z możliwością edycji. Stackblitz powinien automatycznie uruchomić aplikację. Możesz zacząć!
Alternatywa: sklonuj repozytorium i udostępnij aplikację
Korzystanie z VS Code lub lokalnego IDE to alternatywna metoda wykonywania tych ćwiczeń z programowania:
- Otwórz nową kartę przeglądarki i wejdź na stronę https://github.com/angular/codelabs/tree/signals-get-started.
- Utwórz fork i sklonuj repozytorium, a następnie użyj polecenia
cd codelabs/, aby przejść do repozytorium. - Sprawdź gałąź kodu startowego za pomocą polecenia
git checkout signals-get-started. - Otwórz kod w VSCode lub w ulubionym IDE.
- Aby zainstalować zależności wymagane do uruchomienia serwera, użyj polecenia
npm install. - Aby uruchomić serwer, użyj polecenia
ng serve. - Otwórz kartę przeglądarki z adresem http://localhost:4200.
3. Ustalenie wartości odniesienia
Punktem wyjścia jest gra Angular Cipher, ale jeszcze nie działa. Funkcje gry będą oparte na sygnałach Angulara.

Na początek zapoznaj się z gotową wersją tego, co będziesz tworzyć: Angular Signals Cypher.
- Wyświetl zakodowaną wiadomość na ekranie.
- Przeciągnij i upuść przycisk z literą na klawiaturze, aby rozwiązać szyfr i odszyfrować tajną wiadomość.
- Jeśli Ci się uda, zobaczysz, jak wiadomość się zmienia, aby odszyfrować więcej jej fragmentów.
- Kliknij Dostosuj, aby zmienić nadawcę i wiadomość, a potem kliknij Utwórz i skopiuj URL, aby zobaczyć wartości na ekranie i zmianę adresu URL.
- Dodatkowo: skopiuj i wklej adres URL na nowej karcie lub udostępnij go znajomemu i sprawdź, jak nadawca i wiadomość są przechowywane w adresie URL.

4. Definiowanie pierwszego sygnału()
Sygnał to wartość, która może informować Angulara o zmianie. Niektóre sygnały można zmieniać bezpośrednio, a inne obliczają swoje wartości na podstawie wartości innych sygnałów. Sygnały tworzą skierowany graf zależności, który modeluje przepływ danych w aplikacji.
Angular może używać powiadomień z sygnałów, aby określać, które komponenty wymagają wykrywania zmian, lub wykonywać zdefiniowane przez Ciebie funkcje efektu.
Przekształć superSecretMessage w signal()
superSecretMessage to wartość w MessageService, która określa tajną wiadomość, jaką gracz musi odszyfrować. Obecnie wartość nie powiadamia aplikacji o zmianach, więc przycisk Dostosuj nie działa. Możesz to rozwiązać za pomocą sygnału.
Ustawiając superSecretMessage jako sygnał, możesz powiadamiać części aplikacji, które zależą od informacji o zmianie wiadomości. Gdy dostosujesz wiadomość w oknie dialogowym, ustawisz sygnał, aby zaktualizować resztę aplikacji o nową wiadomość.
Aby zdefiniować pierwszy sygnał, wykonaj te czynności w sekcji komentarza TODO(1): Define your first signal() w każdym pliku:
- W pliku
service.message.tsużyj biblioteki Signals, aby uczynićsuperSecretMessagereaktywnym:
src/app/secret-message/service.message.ts
superSecretMessage = signal(
'Angular Signals are in developer preview in v16 today!'
);
Automatycznie pojawi się prośba o zaimportowanie signal z @angular/core. Jeśli odświeżysz stronę, prawdopodobnie wystąpią błędy w miejscach, w których wcześniej użyto symbolu superSecretMessage. Dzieje się tak, ponieważ zmieniono typ superSecretMessage z string na SettableSignal<string>. Aby rozwiązać ten problem, zmień wszystkie odwołania do superSecretMessage, aby korzystać z interfejsu Signals API. W każdym miejscu, w którym odczytujesz wartość, wywołaj funkcję pobierającą sygnał superSecretMessage(). W miejscu, w którym wpisujesz wartość, użyj interfejsu .set API w SettableSignal, aby ustawić nową wartość wiadomości.
- W plikach
secret-message.tsiservice.message.tszaktualizuj wszystkie odwołania dosuperSecretMessagenasuperSecretMessage():
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()
Poznaj 2 pozostałe sygnały
- Zwróć uwagę, że w aplikacji masz 2 inne sygnały:
src/app/cipher/service.cipher.ts
cipher = signal(this.createNewCipherKey());
decodedCipher = signal<CipherKey[]>([]);
Znak CipherService definiuje cipher sygnał, czyli losowo wygenerowane mapowanie par klucz-wartość składających się z jednej litery alfabetu na nową cipher literę. Używasz go do zaszyfrowania wiadomości i sprawdzenia, czy gracz znajdzie odpowiednie dopasowanie na klawiaturze.
Masz też sygnał decodedCipher, który wskazuje, że pary klucz-wartość zostały prawidłowo zdekodowane. Będziesz go uzupełniać w miarę rozwiązywania szyfru przez gracza.
Unikalną i ważną cechą biblioteki sygnałów Angulara jest to, że reaktywność można wprowadzić wszędzie. Sygnały definiujesz raz w usługach aplikacji i możesz ich używać w szablonie, komponentach, potokach, innych usługach lub w dowolnym miejscu, w którym możesz pisać kod aplikacji. Nie są one ograniczone do zakresu komponentu.
Weryfikowanie zmian
- Zanim aplikacja zacznie działać, musisz wykonać jeszcze jeden krok. Na razie spróbuj dodać
console.log()w różnych częściach aplikacji, aby sprawdzić, jak ustawiana jest nowasuperSecretMessage.

5. Określanie pierwszej funkcji computed()
W wielu sytuacjach możesz wywnioskować stan na podstawie istniejących wartości. Lepiej jest aktualizować stan pochodny, gdy zmieni się wartość zależna.
Za pomocą atrybutu computed() możesz deklaratywnie wyrazić sygnał, którego wartość pochodzi z innych sygnałów.
Przekształć solvedMessage w computed()
solvedMessage tłumaczy wartość secretMessage z zakodowanej na odkodowaną za pomocą sygnału decodedCipher.
Jest to szczególnie przydatne, ponieważ możesz zobaczyć, że obliczenia są wykonywane na podstawie innych obliczeń, więc za każdym razem, gdy sygnał w mapowanym kontekście reaktywnym ulegnie zmianie, zależności są o tym powiadamiane.
Obecnie solvedMessage nie jest aktualizowany, gdy zmienisz secretMessage, decodedCipher lub superSecretMessage. Dlatego nie widzisz aktualizacji ekranu, gdy gracz rozwiązuje szyfr.
Dzięki przekształceniu solvedMessage w wartość obliczaną tworzysz kontekst reaktywny, dzięki czemu po zaktualizowaniu wiadomości lub rozwiązaniu szyfru możesz wywnioskować aktualizację stanu ze śledzonych zależności.
Aby przekonwertować solvedMessage na computed(), wykonaj te czynności w sekcji komentarza TODO(2): Define your first computed() w każdym pliku:
- W pliku
service.message.tsużyj biblioteki Signals, aby uczynićsolvedMessagereaktywnym:
src/app/secret-message/service.message.ts
solvedMessage = computed(() =>
this.translateMessage(
this.secretMessage(),
this.cipher.decodedCipher()
)
);
Automatycznie pojawi się prośba o zaimportowanie computed z @angular/core. Jeśli odświeżysz stronę, prawdopodobnie wystąpią błędy w miejscach, w których wcześniej użyto symbolu solvedMessage. Dzieje się tak, ponieważ typ superSecretMessage został zmieniony z string na Signal<string>, czyli funkcję. Aby to naprawić, zmień wszystkie odwołania do solvedMessage na solvedMessage().
- W pliku
secret-message.tszmień wszystkie odwołania dosolvedMessagenasolvedMessage():
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>
Pamiętaj, że w przeciwieństwie do superSecretMessage, solvedMessage nie jest SettableSignal – nie możesz bezpośrednio zmienić jego wartości. Jego wartość jest aktualizowana za każdym razem, gdy zmienia się jeden z sygnałów zależnych (secretMessage i decodedCipher).
Poznaj 2 pozostałe computed() funkcje
- Zauważ, że w aplikacji masz 2 inne obliczone wartości:
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)
)
);
MessageService określa secretMessage obliczoną superSecretMessage zakodowaną przez cipher, którą gracze muszą rozwiązać.
Pole CipherService określa unsolvedAlphabet obliczoną listę wszystkich liter, których gracz jeszcze nie odgadł. Jest ona wyodrębniana z listy odgadniętych kluczy szyfru w polu decodedCipher.
Weryfikowanie zmian
Teraz, gdy superSecretMessage jest sygnałem, a solvedMessage jest wartością obliczoną, aplikacja powinna działać. Sprawdź funkcje gry:
- Przeciągnij i upuść
LetterGuessComponentnaLetterKeyComponentwCipherComponent, aby rozwiązać szyfr i odszyfrować tajną wiadomość. - Sprawdź, jak
SecretMessageComponentzmienia się w miarę odszyfrowywania tajnej wiadomości. - Kliknij Dostosuj, aby zmienić nadawcę i wiadomość, a potem kliknij Utwórz i skopiuj URL, aby zobaczyć wartości na ekranie i zmianę adresu URL.
- Dodatkowo: skopiuj i wklej adres URL na nowej karcie lub udostępnij go znajomemu i sprawdź, jak nadawca i wiadomość są przechowywane w adresie URL.

6. Dodaj pierwszy efekt()
Czasami możesz chcieć, aby coś się wydarzyło, gdy sygnał przyjmie nową wartość. Za pomocą effect() możesz zaplanować i uruchomić funkcję obsługi w odpowiedzi na zmianę sygnałów.
Dodawanie konfetti po rozwiązaniu szyfru
Teraz, gdy aplikacja działa, możesz dodać trochę zabawy, wyświetlając konfetti po rozwiązaniu mechanizmu szyfrowania i zdekodowaniu tajnej wiadomości.
Aby dodać konfetti, wykonaj te czynności w sekcji TODO(3): Add your first effect() comment:
- W pliku
cipher.tszaplanuj efekt, aby dodać konfetti po zdekodowaniu wiadomości:
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 });
}
});
}
Zwróć uwagę, że ten efekt zależy od sygnału i obliczonej wartości: this.messages.superSecretMessage() i this.messages.solvedMessage().
Efekt pomaga zaplanować funkcję konfetti w kontekście reaktywnym, aby śledzić i ponownie oceniać, kiedy aktualizowane są jego zależności.
Weryfikowanie zmian
- Spróbuj rozwiązać szyfr (wskazówka: możesz zmienić wiadomość na krótką, aby szybciej przetestować rozwiązanie). Wyskakujące konfetti pogratuluje Ci pierwszego
effect()!

7. Gratulacje!
Twój szyfr kątowy jest gotowy do odszyfrowywania i udostępniania tajnych wiadomości. Chcesz przekazać wiadomość zespołowi Angular? Oznacz nasze profile w mediach społecznościowych tagiem @Angular, abyśmy mogli je odczytać. 🎉

W zestawie narzędzi Angular masz teraz 3 nowe reaktywne elementy podstawowe, które upraszczają proces tworzenia aplikacji i domyślnie przyspieszają ich działanie.
Więcej informacji
Zapoznaj się z tymi ćwiczeniami:
- Pierwsze kroki z samodzielnymi komponentami
- Tworzenie aplikacji internetowej za pomocą Angulara i Firebase
Zapoznaj się z tymi materiałami:
- Angular.io
- Rethinking Reactivity with Signals (Google I/O 2023)
- Co nowego w Angularze (Google I/O 2023)