شروع کار با سیگنال های زاویه ای

۱. قبل از شروع

لوگوی مشکی زاویه‌دار

Angular Signals سه نوع داده اولیه واکنشی را به Angular که می‌شناسید و دوست دارید معرفی می‌کند و توسعه شما را ساده کرده و به شما کمک می‌کند تا به طور پیش‌فرض برنامه‌های سریع‌تری بسازید.

آنچه خواهید ساخت

  • شما با سه نوع داده واکنشی اولیه که با Angular Signals معرفی شده‌اند آشنا می‌شوید: signal() ، computed() و effect() .
  • از Angular Signals برای تقویت یک بازی Angular Cipher استفاده کنید. Cipherها سیستم‌هایی برای رمزگذاری و رمزگشایی داده‌ها هستند. در این بازی، کاربران می‌توانند با کشیدن و رها کردن سرنخ‌ها برای حل یک رمز، یک پیام مخفی را رمزگشایی کنند، پیام را سفارشی کنند و URL را برای ارسال پیام‌های مخفی به دوستان به اشتراک بگذارند.

بازی Angular Cypher به سبک یک کنسول بازی سبز قدیمی، با یک پیام مخفی روی صفحه نمایش «Anqnxaa Lpcnaxl aaf pn jfafxyofa aofapfm pn a16 wyjak!»

پیش‌نیازها

  • آشنایی با Angular و Typescript
  • توصیه می‌شود: برای آشنایی با کتابخانه‌ی Angular Signals، فیلم آموزشی Rethinking Reactivity with Signals را تماشا کنید.

۲. کد را دریافت کنید

هر چیزی که برای این پروژه نیاز دارید در یک Stackblitz موجود است. Stackblitz روش پیشنهادی برای کار با این codelab است. به عنوان یک جایگزین، کد را کپی کرده و آن را در محیط توسعه مورد علاقه خود باز کنید.

Stackblitz را باز کنید و برنامه را اجرا کنید.

برای شروع، لینک Stackblitz را در مرورگر وب مورد علاقه خود باز کنید:

  1. یک تب جدید در مرورگر باز کنید و به آدرس https://stackblitz.com/edit/io-signals-codelab-starter?file=src%2Fcipher%2Fservice.cipher.ts,src%2Fsecret-message%2Fservice.message.ts&service.massage.ts بروید.
  2. برای ایجاد فضای کاری قابل ویرایش خود، Stackblitz را منشعب کنید. Stackblitz باید به طور خودکار برنامه را اجرا کند و شما آماده شروع به کار هستید!

جایگزین: مخزن را کلون کنید و برنامه را اجرا کنید

استفاده از VSCode یا یک IDE محلی، روش جایگزین برای کار با این codelab است:

  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 بروید.

۳. یک خط پایه ایجاد کنید

نقطه شروع شما یک بازی 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) ذخیره می‌شوند.

گیف بازی Angular Cypher، با پیامی مخفی که روی صفحه رمزگشایی می‌شود و این جمله را می‌گوید: «Angular Signals امروز در نسخه ۱۶ در پیش‌نمایش توسعه‌دهندگان قرار دارد!»

۴. اولین تابع signal() خود را تعریف کنید.

سیگنال مقداری است که می‌تواند به Angular بگوید چه زمانی تغییر می‌کند. برخی از سیگنال‌ها را می‌توان مستقیماً تغییر داد، در حالی که برخی دیگر مقادیر خود را از مقادیر سیگنال‌های دیگر محاسبه می‌کنند. سیگنال‌ها با هم یک نمودار جهت‌دار از وابستگی‌ها ایجاد می‌کنند که نحوه جریان داده‌ها در برنامه شما را مدل‌سازی می‌کند.

انگولار می‌تواند از اعلان‌های سیگنال‌ها استفاده کند تا بداند کدام کامپوننت‌ها نیاز به تشخیص تغییر دارند یا توابع تأثیرگذاری که شما تعریف می‌کنید را اجرا کند.

تبدیل superSecretMessage به یک signal()

superSecretMessage مقداری در MessageService است که پیام مخفی که پخش‌کننده رمزگشایی می‌کند را تعریف می‌کند. در حال حاضر، این مقدار برنامه را از تغییرات مطلع نمی‌کند، بنابراین دکمه Customize خراب است. می‌توانید این مشکل را با یک سیگنال حل کنید.

با تبدیل 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 برطرف کنید. هر جا که مقدار را می‌خوانید، getter سیگنال 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 را در حال ثبت صحیح پیام جدید نشان می‌دهد.

۵. اولین تابع computed() خود را تعریف کنید

در بسیاری از موقعیت‌ها ممکن است خود را در حال استخراج حالت از مقادیر موجود بیابید. بهتر است حالت مشتق شده با تغییر مقدار وابسته به‌روزرسانی شود.

با computed() می‌توانید به صورت اعلانی سیگنالی را بیان کنید که مقدار خود را از سیگنال‌های دیگر می‌گیرد.

تبدیل solvedMessage به یک computed()

solvedMessage با استفاده از سیگنال decodedCipher ، مقدار secretMessage را از حالت کدگذاری شده به حالت رمزگشایی شده تبدیل می‌کند.

این خیلی جالب است زیرا می‌توانید ببینید که یک محاسبه‌شده را بر اساس یک محاسبه‌شده دیگر استخراج می‌کنید، بنابراین هر زمان که سیگنالی در آن زمینه واکنشی نگاشت‌شده تغییر کند، وابستگی‌ها مطلع می‌شوند.

در حال حاضر، وقتی شما secretMessage ، decodedCipher یا superSecretMessage را تغییر می‌دهید، solvedMessage به‌روزرسانی نمی‌شود. بنابراین وقتی بازیکن رمز را حل می‌کند، به‌روزرسانی‌هایی روی صفحه مشاهده نمی‌کنید.

با تبدیل 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) ذخیره می‌شوند.

گیف بازی Angular Cypher، با پیامی مخفی که روی صفحه رمزگشایی می‌شود و این جمله را می‌گوید: «Angular Signals امروز در نسخه ۱۶ در پیش‌نمایش توسعه‌دهندگان قرار دارد!»

۶. اولین افکت خود را اضافه کنید()

مواقعی وجود دارد که ممکن است بخواهید وقتی یک سیگنال مقدار جدیدی دارد، اتفاقی بیفتد. با استفاده از effect() می‌توانید یک تابع کنترل‌کننده را در پاسخ به تغییر سیگنال‌ها برنامه‌ریزی و اجرا کنید.

وقتی رمز حل شد، پولک‌ها را اضافه کنید

حالا که برنامه کاربردی شده است، می‌توانید با اضافه کردن کاغذ رنگی پس از حل شدن رمز و رمزگشایی پیام مخفی، کمی سرگرم‌کننده‌تر شوید.

برای اضافه کردن رنگ‌های کنفی، مراحل زیر را در TODO(3): Add your first effect() :

  1. در فایل cipher.ts ، افکتی را برنامه‌ریزی کنید تا پس از رمزگشایی پیام، رنگ‌های کنفی (confetti) اضافه شوند:

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 });
    }
  });
}

توجه کنید که چگونه این اثر به یک سیگنال و یک مقدار محاسبه‌شده بستگی دارد: this.messages.superSecretMessage() و this.messages.solvedMessage() .

Effect به شما کمک می‌کند تا تابع confetti را درون یک زمینه واکنشی زمان‌بندی کنید تا هنگام به‌روزرسانی وابستگی‌های آن، بتوانید آنها را ردیابی و دوباره ارزیابی کنید.

تأیید تغییرات

  • سعی کنید رمز را حل کنید (راهنمایی: می‌توانید پیام را به چیزی کوتاه تغییر دهید تا سریع‌تر آزمایش کنید!). یک پاپِ کُفتی به شما به خاطر اولین effect() !

گیف بازی Angular Cypher، که در آن یک پیام مخفی روی صفحه رمزگشایی می‌شود و عبارت «وقت پولک‌های رنگی است!» را هجی می‌کند و وقتی پیام حل می‌شود، پاپرهای پولک رنگی به صدا در می‌آیند.

۷. تبریک می‌گویم!

اکنون Angular Cipher شما آماده رمزگشایی و اشتراک‌گذاری پیام‌های مخفی است! پیامی برای تیم Angular دارید؟ در شبکه‌های اجتماعی ما، @Angular را تگ کنید تا بتوانیم آن را رمزگشایی کنیم! 🎉

مشکل بازی Angular Cypher با یک پیام مخفی روی صفحه با مضمون «Angular Signals امروز در نسخه ۱۶ پیش‌نمایش توسعه‌دهندگان قرار دارد!» حل شد.

اکنون سه شیء واکنشی جدید در جعبه ابزار Angular خود دارید که به طور پیش‌فرض توسعه شما را ساده کرده و برنامه‌های سریع‌تری می‌سازند.

بیشتر بدانید

این آزمایشگاه‌های کد را بررسی کنید:

این مطالب را بخوانید: