Начало работы с угловыми сигналами

1. Прежде чем начать

черный угловой логотип

Angular Signals представляет три реактивных примитива в Angular, которые вы знаете и любите, упрощая вашу разработку и помогая создавать более быстрые приложения по умолчанию.

Что ты построишь

  • Вы узнаете о трех реактивных примитивах, представленных в Angular Signals: signal() , computed() и effect() .
  • Используйте сигналы Angular для запуска игры Angular Cipher. Шифры — это системы шифрования и дешифрования данных. В этой игре пользователи могут расшифровать секретное сообщение, перетаскивая подсказки, чтобы разгадать шифр, настроить сообщение и поделиться URL-адресом для отправки секретных сообщений друзьям.

Игра Angular Cypher в стиле винтажной зеленой игровой консоли со скрытым сообщением на экране «Anqnxaa Lpcnaxl aaf pn jfafxyofa aofapfm pn a16 wyjak!»

Предварительные условия

2. Получите код

Все, что вам нужно для этого проекта, находится в Stackblitz. Stackblitz — рекомендуемый метод для работы с этой лабораторией кода. В качестве альтернативы клонируйте код и откройте его в своей любимой среде разработки.

Откройте Stackblitz и запустите приложение.

Чтобы начать, откройте ссылку Stackblitz в своем любимом веб-браузере:

  1. Откройте новую вкладку браузера и перейдите по адресу https://stackblitz.com/edit/io-signals-codelab-starter?file=src%2Fcipher%2Fservice.cipher.ts,src%2Fsecret-message%2Fservice.message.ts&service. массаж.ц
  2. Форк Stackblitz, чтобы создать собственное редактируемое рабочее пространство. Stackblitz должен автоматически запустить приложение, и все готово!

Альтернатива: клонировать репозиторий и использовать приложение.

Использование VSCode или локальной IDE — альтернативный метод работы с этой лабораторией кода:

  1. Откройте новую вкладку браузера и перейдите по адресу https://github.com/angular/codelabs/tree/signals-get-started .
  2. Создайте форк и клонируйте репозиторий и используйте команду cd codelabs/ для перемещения в репозиторий.
  3. Проверьте ветку стартового кода с помощью команды git checkout signals-get-started .
  4. Откройте код в VSCode или предпочитаемой вами IDE.
  5. Чтобы установить зависимости, необходимые для запуска сервера, используйте команду npm install .
  6. Чтобы запустить сервер, используйте команду ng serve .
  7. Откройте вкладку браузера по адресу http://localhost:4200 .

3. Установите базовый уровень

Ваша отправная точка — игра Angular Cipher, но она пока не работает. Angular Signals обеспечит функциональность игры.

Игра Angular Cypher в стиле винтажной зеленой игровой консоли со скрытым сообщением на экране «Anqnxaa Lpcnaxl aaf pn jfafxyofa aofapfm pn a16 wyjak!»

Для начала ознакомьтесь с готовой версией того, что вы будете создавать: Angular Signals Cypher .

  1. Просмотрите закодированное сообщение на экране.
  2. Перетащите кнопку с буквой на клавиатуре, чтобы разгадать шифр и расшифровать секретное сообщение.
  3. В случае успеха посмотрите, как сообщение обновляется, чтобы расшифровать больше секретного сообщения.
  4. Нажмите «Настроить», чтобы изменить отправителя и сообщение, а затем нажмите «Создать и скопировать URL-адрес» , чтобы увидеть значения на экране и изменение URL-адреса.
  5. Бонус: скопируйте и вставьте URL-адрес в новую вкладку или поделитесь им с другом и посмотрите, как отправитель и сообщение хранятся в URL-адресе.

GIF-изображение игры Angular Cypher со скрытым сообщением, которое декодируется на экране и означает: «Сегодня Angular Signals находятся в предварительной версии для разработчиков в версии 16!»

4. Определите свой первый сигнал()

Сигнал — это значение, которое может сообщить Angular об изменении. Некоторые сигналы можно изменять напрямую, тогда как другие вычисляют свои значения на основе значений других сигналов. Вместе сигналы создают ориентированный граф зависимостей, который моделирует поток данных в вашем приложении.

Angular может использовать уведомления от сигналов, чтобы узнать, какие компоненты необходимо обнаружить, или выполнить определенные вами функции эффектов .

Преобразовать superSecretMessage в signal()

superSecretMessage — это значение в MessageService , которое определяет секретное сообщение, которое декодирует игрок. В настоящее время значение не уведомляет приложение об изменениях, поэтому кнопка «Настроить» не работает. Решить это можно с помощью сигнала.

Сделав superSecretMessage сигналом, вы можете уведомить части приложения, которые зависят от того, когда сообщение изменилось. Когда вы настраиваете сообщение в диалоговом окне, вы устанавливаете сигнал для обновления остальной части приложения новым сообщением.

Чтобы определить свой первый сигнал, выполните следующие шаги в разделе TODO(1): Define your first signal() в каждом файле:

  1. В файле service.message.ts используйте библиотеку Signals, чтобы сделать superSecretMessage реактивным:

src/app/secret-message/service.message.ts

superSecretMessage = signal(
  'Angular Signals are in developer preview in v16 today!'
);

Это автоматически предложит вам импортировать signal из @angular/core . Если вы обновите страницу, вы, скорее всего, столкнетесь с ошибками там, где вы ранее ссылались на superSecretMessage . Это связано с тем, что вы изменили тип superSecretMessage со string на SettableSignal<string> . Вы можете исправить это, изменив все ссылки superSecretMessage на использование Signals API. Где бы вы ни прочитали значение, вызовите метод получения сигнала superSecretMessage() . И где бы вы ни записывали значение, используйте API .set в SettableSignal чтобы установить новое значение для сообщения.

  1. В файлах secret-message.ts и service.message.ts обновите все ссылки superSecretMessage на superSecretMessage() :

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()

Изучите два других сигнала

  • Обратите внимание, что в вашем приложении есть еще два сигнала:

src/app/cipher/service.cipher.ts

cipher = signal(this.createNewCipherKey());
decodedCipher = signal<CipherKey[]>([]);

CipherService определяет сигнал cipher — случайно сгенерированное сопоставление пар ключ-значение одной буквы алфавита с новой буквой cipher . Вы используете это, чтобы зашифровать сообщение и определить, находит ли игрок успешное совпадение на клавиатуре.

У вас также есть сигнал decodedCipher об успешно декодированных парах ключ-значение, который вы будете добавлять по мере того, как игрок разгадывает шифр.

Уникальным и мощным свойством дизайна библиотеки Signals Angular является то, что вы можете внедрить реактивность повсюду. Вы определили сигналы один раз в службах приложения и можете использовать их в шаблоне, компонентах, каналах, других службах или везде, где можно писать код приложения. Они не ограничены и не привязаны к области действия компонента.

Проверьте изменения

  • Вам нужно выполнить еще один шаг, прежде чем приложение заработает. А пока попробуйте добавить console.log() в разные части вашего приложения, чтобы увидеть, как устанавливается ваше новое superSecretMessage .

Stackblitz с сообщением console.log(), показывающим, что superSecretMessage правильно регистрирует новое сообщение.

5. Определите свой первый вычисляемый()

Во многих ситуациях вы можете обнаружить, что получаете состояние из существующих значений. Лучше обновлять производное состояние при изменении зависимого значения.

С помощью computed() вы можете декларативно выразить сигнал, который получает свое значение из других сигналов.

Преобразовать solvedMessage в computed()

solvedMessage преобразует значение secretMessage из закодированного в декодированное с помощью сигнала decodedCipher .

Это очень здорово, потому что вы можете видеть, что вы получаете вычисленное значение на основе другого вычисленного, поэтому каждый раз, когда сигнал в этом сопоставленном реактивном контексте изменяется, зависимости уведомляются.

В настоящее solvedMessage не обновляется при изменении secretMessage , decodedCipher или superSecretMessage . Таким образом, вы не видите обновлений на экране, когда игрок разгадывает шифр.

solvedMessage вычисляемым, вы создаете реактивный контекст, чтобы при обновлении сообщения или раскрытии шифра вы могли получить обновление состояния из отслеживаемых зависимостей.

Чтобы преобразовать solvedMessage в computed() , выполните следующие шаги в TODO(2): Define your first computed() в каждом файле:

  1. В файле service.message.ts используйте библиотеку Signals, чтобы solvedMessage реактивным:

src/app/secret-message/service.message.ts

solvedMessage = computed(() =>
  this.translateMessage(
    this.secretMessage(), 
    this.cipher.decodedCipher()
  )
);

Это автоматически предложит вам импортировать computed из @angular/core . Если вы обновите страницу, вы, скорее всего, столкнетесь с ошибками там, где вы ранее ссылались solvedMessage . Это связано с тем, что вы изменили тип superSecretMessage со string на функцию Signal<string> . Вы можете исправить это, изменив все solvedMessage solvedMessage() .

  1. В файле secret-message.ts обновите все solvedMessage solvedMessage() :

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>

Обратите внимание: в отличие от superSecretMessage , solvedMessage не является SettableSignal — вы не можете изменить его значение напрямую. Вместо этого его значение обновляется всякий раз, когда обновляется любой из его сигналов зависимости ( secretMessage и decodedCipher ).

Изучите две другие функции computed()

  • Обратите внимание, что в вашем приложении есть еще два вычисляемых значения:

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 определяет вычисленное secretMessage , superSecretMessage , закодированное cipher , над разгадкой которого работают игроки.

CipherService определяет вычисленный unsolvedAlphabet — список всех букв, которые игрок не разгадал, который получается из списка решенных ключей шифрования в decodedCipher .

Проверьте изменения

Теперь, когда superSecretMessage является сигналом, solvedMessage — вычисляемым, приложение должно работать! Оцените возможности игры:

  1. Перетащите компонент LetterGuessComponent в LetterKeyComponent в CipherComponent , чтобы работать над решением шифра и декодированием секретного сообщения.
  2. Посмотрите, как обновляется SecretMessageComponent по мере декодирования секретного сообщения.
  3. Нажмите «Настроить», чтобы изменить отправителя и сообщение, а затем нажмите «Создать и скопировать URL-адрес» , чтобы увидеть значения на экране и изменение URL-адреса.
  4. Бонус: скопируйте и вставьте URL-адрес в новую вкладку или поделитесь им с другом и посмотрите, как отправитель и сообщение хранятся в URL-адресе.

GIF-изображение игры Angular Cypher со скрытым сообщением, которое декодируется на экране и означает: «Сегодня Angular Signals находятся в предварительной версии для разработчиков в версии 16!»

6. Добавьте свой первый эффект()

Бывают случаи, когда вам может потребоваться, чтобы что-то произошло, когда сигнал имеет новое значение. С помощью effect() вы можете запланировать и запустить функцию-обработчик в ответ на изменение сигналов.

Добавьте конфетти, когда шифр будет раскрыт.

Теперь, когда приложение работает, вы можете добавить немного веселья, добавив конфетти, когда шифр разгадан и секретное сообщение расшифровано.

Чтобы добавить конфетти, выполните следующие шаги в TODO(3): Add your first effect() :

  1. В файле cipher.ts запланируйте эффект добавления конфетти при декодировании сообщения:

src/приложение/шифр/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 });
    }
  });
}

Обратите внимание, как этот эффект зависит от сигнала и вычисленного значения: this.messages.superSecretMessage() и this.messages.solvedMessage() .

Эффект помогает запланировать функцию конфетти внутри реактивного контекста для отслеживания и повторной оценки при обновлении ее зависимостей.

Проверьте изменения

  • Попробуйте разгадать шифр (подсказка: вы можете изменить сообщение на что-нибудь короткое, чтобы быстрее проверить!). Конфетти поздравит вас с первым effect() !

GIF-изображение игры Angular Cypher со скрытым сообщением, которое декодируется на экране и образует «Время конфетти!» и хлопушки с конфетти взрываются, когда сообщение решено.

7. Поздравляем!

Ваш Angular Cipher теперь готов декодировать и делиться секретными сообщениями! У вас есть сообщение для команды Angular? Отметьте наши социальные сети @Angular, чтобы мы могли их расшифровать! 🎉

Игра Angular Cypher решена со скрытым сообщением на экране «Сегодня Angular Signals находится в предварительной версии для разработчиков в версии 16!»

Теперь в вашем наборе инструментов Angular есть три новых реактивных примитива, которые по умолчанию упрощают разработку и создают более быстрые приложения.

Узнать больше

Ознакомьтесь с этими лабораториями кода:

Прочтите эти материалы: