1. Antes de começar
Os sinais do Angular introduzem três primitivos reativos ao Angular que você conhece e adora, simplificando seu desenvolvimento e ajudando a criar apps mais rápidos por padrão.
O que você vai criar
- Você aprenderá sobre os três primitivos reativos introduzidos com os sinais do Angular:
signal()
,computed()
eeffect()
. - Use os sinais do Angular para potencializar um jogo de criptografia do Angular. As criptografias são sistemas para criptografar e descriptografar dados. Neste jogo, os usuários podem decodificar uma mensagem secreta arrastando e soltando pistas para resolver uma cifra, personalizar a mensagem e compartilhar o URL para enviar mensagens secretas a amigos.
Pré-requisitos
- Conhecimento sobre Angular e Typescript
- Recomendado: assista ao vídeo Repensando a reatividade com indicadores para saber mais sobre a biblioteca de sinais de Angular.
2. Acessar o código
Tudo o que você precisa para este projeto está em um Stackblitz. O Stackblitz é o método recomendado para trabalhar neste codelab. Como alternativa, clone o código e abra-o no seu ambiente de desenvolvimento favorito.
Abra o Stackblitz e execute o app
Para começar, abra o link do Stackblitz no seu navegador da Web favorito:
- Abra uma nova guia do navegador e acesse https://stackblitz.com/edit/io-signals-codelab-starter?file=src%2Fcipher%2Fservice.cipher.ts,src%2Fsecret-message%2Fservice.message.ts&service.massage.ts
- Bifurque o Stackblitz para criar seu próprio espaço de trabalho editável. O Stackblitz executará o app automaticamente, e você estará pronto para começar.
Alternativa: clonar o repositório e exibir o app
Usar o VSCode ou um ambiente de desenvolvimento integrado local é um método alternativo para trabalhar com este codelab:
- Abra uma nova guia do navegador e acesse https://github.com/angular/codelabs/tree/signals-get-started.
- Copie e clone o repositório e use o comando
cd codelabs/
para acessar o repositório. - Confira a ramificação do código inicial com o comando
git checkout signals-get-started
. - Abra o código no VSCode ou no ambiente de desenvolvimento integrado de sua preferência.
- Para instalar as dependências necessárias para executar o servidor, use o comando
npm install
. - Para executar o servidor, use o comando
ng serve
. - Abra uma guia do navegador e acesse http://localhost:4200.
3. Definir um valor de referência
Seu ponto de partida é um jogo de criptografia do Angular, mas ele ainda não está funcionando. Os sinais do Angular vão melhorar a funcionalidade do jogo.
Para começar, veja a versão final do que você criará: Cypher de sinais de Angular.
- Veja a mensagem codificada na tela.
- Arraste e solte o botão de letra no teclado para resolver a cifra e decodificar a mensagem secreta.
- Em caso de sucesso, veja como a mensagem é atualizada para decodificar mais mensagens secretas.
- Clique em Personalizar para alterar o remetente e a mensagem. Em seguida, clique em Criar e copiar URL para ver os valores na tela e o URL ser alterado.
- Bônus: copie e cole o URL em uma nova guia ou compartilhe com um amigo para ver como o remetente e a mensagem são armazenados no URL.
4. Definir seu primeiro sinal()
Um sinal é um valor que pode informar ao Angular quando ele mudar. Alguns indicadores podem ser alterados diretamente, enquanto outros calculam os valores deles. Juntos, os indicadores criam um gráfico direcionado de dependências que modela como os dados fluem no seu app.
O Angular pode usar as notificações de sinais para saber quais componentes precisam ser detectados para a alteração ou executar funções de efeito que você define.
Converter superSecretMessage
em um signal()
superSecretMessage
é um valor em MessageService
que define a mensagem secreta decodificada pelo jogador. Atualmente, o valor não notifica o app sobre as mudanças, então o botão Personalizar está corrompido. Você pode resolver isso com um sinal.
Ao fazer com que o superSecretMessage
sinalize, é possível notificar partes do app que dependem de saber quando a mensagem mudou. Ao personalizar a mensagem em uma caixa de diálogo, você definirá o sinal para atualizar o restante do app com a nova mensagem.
Para definir seu primeiro indicador, siga as etapas abaixo no comentário TODO(1): Define your first signal()
em cada arquivo:
- No arquivo
service.message.ts
, use a biblioteca Signals para tornarsuperSecretMessage
reativo:
src/app/secret-message/service.message.ts
superSecretMessage = signal(
'Angular Signals are in developer preview in v16 today!'
);
Isso solicita automaticamente a importação de signal
de @angular/core
. Se você atualizar a página, provavelmente vai encontrar erros em que se referiu a superSecretMessage
. Isso ocorre porque você alterou o tipo de superSecretMessage
de string
para SettableSignal<string>
. Para corrigir isso, altere todas as referências de superSecretMessage
para usar a API Signals. Sempre que você ler o valor, chame o getter de sinal superSecretMessage()
. E sempre que você gravar o valor, use a API .set
em SettableSignal
para definir o novo valor para a mensagem.
- Nos arquivos
secret-message.ts
eservice.message.ts
, atualize todas as referências desuperSecretMessage
parasuperSecretMessage()
:
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 (link em inglês)
// Before
this.superSecretMessage
// After
this.superSecretMessage()
Explorar os outros dois sinais
- Você tem dois outros sinais no app:
src/app/cipher/service.cipher.ts (link em inglês)
cipher = signal(this.createNewCipherKey());
decodedCipher = signal<CipherKey[]>([]);
O CipherService
define um sinal cipher
, um mapeamento gerado aleatoriamente de pares de chave-valor de uma letra do alfabeto para uma nova letra cipher
. Use isso para embaralhar a mensagem e determinar se o player encontra uma correspondência bem-sucedida no teclado.
Você também tem um sinal decodedCipher
dos pares de chave-valor decodificados que serão adicionados quando o player resolver a criptografia.
Um atributo exclusivo e poderoso do design da biblioteca de sinais do Angular é que você pode introduzir reatividade em qualquer lugar. Você definiu os sinais uma vez nos serviços do aplicativo e pode usá-los em um modelo, componentes, barras verticais, outros serviços ou em qualquer lugar em que possa escrever o código do aplicativo. Eles não estão limitados ou vinculados a um escopo de componente.
Verificar alterações
- Você tem mais uma etapa a ser executada antes que o aplicativo funcione. Por enquanto, adicione um
console.log()
em diferentes partes do app para ver como o novosuperSecretMessage
está sendo definido.
5. Defina seu primeiro compute()
Em muitas situações, você pode se deparar com um estado derivando dos valores existentes. É melhor atualizar o estado derivado quando o valor dependente muda.
Com o computed()
, você pode expressar um sinal de maneira declarativa que deriva o valor dele de outros indicadores.
Converter solvedMessage
em um computed()
solvedMessage
converte o valor secretMessage
de codificado para decodificado usando o sinal decodedCipher
.
Isso é muito legal, porque é possível ver que você está extraindo um computado com base em outro computado. Assim, sempre que um sinal dentro desse contexto reativo mapeado, as dependências são notificadas.
Atualmente, o solvedMessage
não é atualizado quando você altera secretMessage
, decodedCipher
ou superSecretMessage
. Portanto, você não está vendo atualizações na tela quando o player resolve a criptografia.
Ao tornar solvedMessage
um computado, você cria um contexto reativo para que, quando você atualizar a mensagem ou resolver a criptografia, possa derivar a atualização de estado das dependências rastreadas.
Para converter solvedMessage
em uma computed()
, siga estas etapas no comentário TODO(2): Define your first computed()
em cada arquivo:
- No arquivo
service.message.ts
, use a biblioteca Signals para tornarsolvedMessage
reativo:
src/app/secret-message/service.message.ts (link em inglês)
solvedMessage = computed(() =>
this.translateMessage(
this.secretMessage(),
this.cipher.decodedCipher()
)
);
Isso solicita automaticamente a importação de computed
de @angular/core
. Se você atualizar a página, provavelmente vai encontrar erros em que se referiu a solvedMessage
. Isso ocorre porque você alterou o tipo de superSecretMessage
de string
para Signal<string>
, uma função. Isso pode ser corrigido alterando todas as referências de solvedMessage
para solvedMessage()
.
- No arquivo
secret-message.ts
, atualize todas as referências desolvedMessage
parasolvedMessage()
:
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>
Ao contrário de superSecretMessage
, solvedMessage
não é um SettableSignal
. Não é possível mudar o valor diretamente. Em vez disso, o valor dele é atualizado sempre que um dos indicadores de dependência (secretMessage
e decodedCipher
) é atualizado.
Explore as duas outras funções computed()
- Você tem dois outros valores calculados no seu app:
src/app/secret-message/service.message.ts (link em inglês)
secretMessage = computed(() =>
this.translateMessage(
this.superSecretMessage(),
this.cipher.cipher()
)
);
src/app/cipher/service.cipher.ts (link em inglês)
unsolvedAlphabet = computed(() =>
ALPHABET.filter(
(letter) => !this.decodedCipher().find((guess) => guess.value === letter)
)
);
O MessageService
define um secretMessage
calculado, o superSecretMessage
codificado pelo cipher
que os jogadores trabalham para resolver.
O CipherService
define um unsolvedAlphabet
calculado, uma lista de todas as letras que o jogador não resolveu, derivada da lista de chaves de criptografia resolvidas em decodedCipher
.
Verificar alterações
Agora que superSecretMessage
é um sinal e solvedMessage
é computado, o app funcionará. Teste as funcionalidades do jogo:
- Arraste e solte um
LetterGuessComponent
em umLetterKeyComponent
noCipherComponent
para resolver a cifra e decodificar a mensagem secreta. - Veja como o
SecretMessageComponent
é atualizado à medida que você decodifica mais da mensagem secreta. - Clique em Personalizar para alterar o remetente e a mensagem. Em seguida, clique em Criar e copiar URL para ver os valores na tela e o URL ser alterado.
- Bônus: copie e cole o URL em uma nova guia ou compartilhe com um amigo para ver como o remetente e a mensagem são armazenados no URL.
6. Adicione seu primeiro efeito()
Há momentos em que você quer que algo ocorra quando um sinal tem um novo valor. Com o effect()
, é possível programar e executar uma função de gerenciador em resposta à mudança de sinais.
Adicionar confete quando a criptografia for resolvida
Agora que o app está funcionando, você pode adicionar confetes quando a criptografia for resolvida e a mensagem secreta for decodificada.
Para adicionar confetes, siga as etapas abaixo no comentário TODO(3): Add your first effect()
:
- No arquivo
cipher.ts
, programe um efeito para adicionar confete quando a mensagem for decodificada:
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 });
}
});
}
Observe como esse efeito depende de um sinal e de um valor calculado: this.messages.superSecretMessage()
e this.messages.solvedMessage()
.
O efeito ajuda a programar a função de confetes dentro de um contexto reativo para rastrear e reavaliar quando as dependências são atualizadas.
Verificar alterações
- Tente resolver a cifra. Dica: você pode alterar a mensagem para algo curto para testar mais rapidamente. Um confete vai parabenizar você no seu primeiro
effect()
!
7. Parabéns!
Seu código do Angular está pronto para decodificar e compartilhar mensagens secretas. Tem uma mensagem para a equipe do Angular? Marque nossa mídia social em @Angular para que possamos decodificá-la. 🎉
Agora você tem três primitivos reativos na caixa de ferramentas do Angular para simplificar o desenvolvimento e criar apps mais rápidos por padrão.
Saiba mais
Confira estes codelabs:
- Primeiros passos com componentes independentes
- Como criar um aplicativo da Web com o Angular e o Firebase
Leia estes materiais:
- Angular.io
- Rethinking Reactivity with Signals: Google I/O 2023
- Novidades no Angular (Google I/O 2023)