תחילת העבודה עם Angular Signals

1. לפני שמתחילים

הלוגו של Angular בשחור

Angular Signals מוסיף שלושה רכיבים בסיסיים ותגובתיים ל-Angular שאתם מכירים ואוהבים, ומפשט את הפיתוח ומאפשר לכם ליצור אפליקציות מהר יותר כברירת מחדל.

מה תפַתחו

  • תלמדו על שלושת הפרימיטיבים הריאקטיביים שהוצגו עם Angular Signals: signal(),‏ computed() ו-effect().
  • שימוש ב-Angular Signals כדי להפעיל משחק של Angular Cipher. הצפנות הן מערכות להצפנה ולפענוח של נתונים. במשחק הזה, המשתמשים יכולים לפענח הודעה סודית על ידי גרירה ושחרור של רמזים כדי לפתור צופן, להתאים אישית את ההודעה ולשתף את כתובת ה-URL כדי לשלוח הודעות סודיות לחברים.

משחק Angular Cypher בסגנון של קונסולת משחקים ירוקה וינטג', עם הודעה מוסתרת במסך: 'Anqnxaa Lpcnaxl aaf pn jfafxyofa aofapfm pn a16 wyjak!'

דרישות מוקדמות

  • ידע ב-Angular וב-Typescript
  • מומלץ: כדאי לצפות בסרטון Rethinking Reactivity with Signals כדי ללמוד על ספריית Signals של Angular.

2. קבל את הקוד

כל מה שצריך לפרויקט הזה נמצא ב-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. יוצרים פורק (fork) ומשכפלים את המאגר, ומשתמשים בפקודה 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 are in developer preview in v16 today!'

4. מגדירים את הפונקציה signal() הראשונה

אות הוא ערך שיכול להודיע ל-Angular מתי הוא משתנה. אפשר לשנות ישירות חלק מהאותות, ואילו אחרים מחושבים על סמך הערכים של אותות אחרים. יחד, האותות יוצרים תרשים מנוהל של יחסי תלות שמציג מודל של זרימת הנתונים באפליקציה.

Angular יכול להשתמש בהתראות מהאותות כדי לדעת באילו רכיבים צריך לזהות שינויים או כדי להריץ פונקציות effect שהוגדרו.

המרה של 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. בכל מקום שבו קוראים את הערך, צריך לקרוא ל-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 של צמדי מפתח/ערך שמפוענחו בהצלחה, שאותם מוסיפים כשהנגן פותר את ההצפנה.

מאפיין ייחודי וחזק של תכנון ספריית האותות של Angular הוא שאפשר להוסיף תגובה מיידית בכל מקום. מגדירים אותות פעם אחת בשירותים של האפליקציה, וניתן להשתמש בהם בתבנית, ברכיבים, בצינורות, בשירותים אחרים או בכל מקום שבו אפשר לכתוב קוד של אפליקציה. הן לא מוגבלות או קשורות להיקף של רכיב.

אימות השינויים

  • נותר עוד שלב אחד לבצע כדי שהאפליקציה תפעל. בינתיים, נסו להוסיף console.log() בחלקים שונים של האפליקציה כדי לראות איך ה-superSecretMessage החדש מוגדר.

Stackblitz עם הודעת console.log()‏ שמראה שההודעה החדשה נרשמה ביומן כראוי על ידי superSecretMessage.

5. הגדרת הפונקציה הראשונה מסוג computed()‎

במקרים רבים, אתם עשויים להסיק את המצב מערכים קיימים. עדיף לעדכן את המצב המשויך כשהערך התלוי משתנה.

בעזרת 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, עם הודעה מוסתרת שמפוענחת במסך ומכילה את הטקסט &#39;Angular Signals are in developer preview in v16 today!&#39;

6. הוספת הפונקציה הראשונה מסוג effect()‎

לפעמים תרצו שיקרה משהו כשלאות יקבל ערך חדש. באמצעות effect() אפשר לתזמן ולהריץ פונקציית handler בתגובה לשינויים באותות.

מוסיפים קונפטי אחרי פתרון ההצפנה

עכשיו, כשהאפליקציה פעילה, אפשר להוסיף קונפטי כשפותרים את ההצפנה ומפענחים את ההודעה הסודית.

כדי להוסיף קונפטי, מבצעים את השלבים הבאים מתחת לתגובה TODO(3): Add your first effect():

  1. בקובץ cipher.ts, מתזמנים אפקט להוספת קונפטי כשההודעה מפענחת:

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() הראשון שלך.

קובץ GIF של המשחק Angular Cypher, עם הודעה נסתרת שמפוענחת במסך ומכילה את הכיתוב &#39;זמן קונפטי!&#39; ופופטי קונפטי מפוענחים כשההודעה נפתרת.

7. מעולה!

המערכת שלכם לקריפטוגרפיה של Angular מוכנה עכשיו לפענוח ולשיתוף של הודעות סודיות. יש לכם הודעה לצוות Angular? אפשר לתייג את חשבונות המדיה החברתית שלנו ב-‎ @Angular כדי שנוכל לפענח אותו. 🎉

פתרון המשחק Angular Cypher עם הודעה מוסתרת במסך: &#39;Angular Signals are in developer preview in v16 today!&#39;

עכשיו יש לכם שלושה פרימיטיבים חדשים של תגובה מיידית בכלי של Angular, שיעזרו לכם לפשט את הפיתוח וליצור אפליקציות מהירות יותר כברירת מחדל.

מידע נוסף

כדאי לעיין בהדרכות הבאות ב-Codelab:

מומלץ לקרוא את המאמרים הבאים: