เริ่มต้นใช้งานสัญญาณ Angular

1. ก่อนเริ่มต้น

โลโก้ Angular สีดำ

Angular Signals จะแนะนำ Reactive Primitive 3 รายการให้กับ Angular ที่คุณรู้จักและชื่นชอบ ซึ่งจะช่วยลดความซับซ้อนในการพัฒนาและช่วยให้คุณสร้างแอปได้เร็วขึ้นโดยค่าเริ่มต้น

สิ่งที่คุณจะสร้าง

  • คุณได้เรียนรู้เกี่ยวกับ Primitive แบบรีแอกทีฟ 3 รายการที่เปิดตัวพร้อมกับ 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 เพื่อดูข้อมูลเกี่ยวกับไลบรารี Angular Signals

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. Fork 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. หากต้องการติดตั้งทรัพยากร Dependency ที่จำเป็นในการเรียกใช้เซิร์ฟเวอร์ ให้ใช้คำสั่ง 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. กำหนด signal() แรก

สัญญาณคือค่าที่บอก Angular ได้เมื่อมีการเปลี่ยนแปลง สัญญาณบางอย่างสามารถเปลี่ยนแปลงได้โดยตรง ในขณะที่สัญญาณอื่นๆ จะคำนวณค่าจากค่าของสัญญาณอื่นๆ สัญญาณจะสร้างกราฟแบบมีทิศทางของ Dependency ที่จำลองวิธีที่ข้อมูลไหลในแอป

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 ไม่ว่าคุณจะอ่านค่าที่ใด ให้เรียกใช้ตัวรับสัญญาณ superSecretMessage() และไม่ว่าคุณจะเขียนค่าที่ใด ให้ใช้ .set API ใน 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()

ดูสัญญาณอื่นๆ อีก 2 รายการ

  • โปรดทราบว่าคุณมีสัญญาณอื่นๆ อีก 2 รายการในแอป ดังนี้

src/app/cipher/service.cipher.ts

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

CipherService กำหนดcipherสัญญาณ ซึ่งเป็นการแมปคู่คีย์-ค่าแบบสุ่มของตัวอักษรหนึ่งตัวในตัวอักษรกับcipherตัวอักษรใหม่ คุณใช้พารามิเตอร์นี้เพื่อสลับข้อความและพิจารณาว่าผู้เล่นจะพบการจับคู่ที่สำเร็จบนแป้นพิมพ์หรือไม่

นอกจากนี้ คุณยังมีdecodedCipherสัญญาณของคู่คีย์-ค่าที่ถอดรหัสสำเร็จแล้ว ซึ่งคุณจะเพิ่มเข้าไปเมื่อผู้เล่นแก้ปริศนาได้

คุณสามารถนำการตอบสนองไปใช้ได้ทุกที่ ซึ่งเป็นคุณลักษณะที่ไม่เหมือนใครและทรงพลังของการออกแบบไลบรารีสัญญาณของ Angular คุณกำหนดสัญญาณครั้งเดียวในบริการของแอป และใช้สัญญาณเหล่านั้นในเทมเพลต คอมโพเนนต์ ไปป์ บริการอื่นๆ หรือที่ใดก็ตามที่คุณเขียนโค้ดแอปพลิเคชันได้ โดยไม่ได้จำกัดหรือผูกมัดกับขอบเขตของคอมโพเนนต์

ยืนยันการเปลี่ยนแปลง

  • คุณต้องทำอีก 1 ขั้นตอนก่อนที่แอปจะทำงานได้ ในตอนนี้ ให้ลองเพิ่ม 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>

โปรดทราบว่า solvedMessage ไม่ใช่ SettableSignal เหมือนกับ superSecretMessage คุณจึงเปลี่ยนค่าของ solvedMessage โดยตรงไม่ได้ แต่ระบบจะอัปเดตค่าของแอตทริบิวต์นี้ทุกครั้งที่มีการอัปเดตสัญญาณการอ้างอิง (secretMessage และ decodedCipher)

สำรวจcomputed() ฟังก์ชันอื่นๆ อีก 2 ฟังก์ชัน

  • โปรดสังเกตว่าคุณมีค่าที่คำนวณแล้วอื่นๆ อีก 2 ค่าในแอป ดังนี้

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 โดยมีข้อความที่ซ่อนอยู่ซึ่งถอดรหัสบนหน้าจอเพื่อสะกดคำว่า &quot;Angular Signals พร้อมให้ใช้งานในเวอร์ชัน 16 ในรูปแบบตัวอย่างสำหรับนักพัฒนาแอปแล้ววันนี้&quot;

6. เพิ่มเอฟเฟกต์แรก()

บางครั้งคุณอาจต้องการให้เกิดบางอย่างเมื่อสัญญาณมีค่าใหม่ effect() ช่วยให้คุณกำหนดเวลาและเรียกใช้ฟังก์ชันตัวแฮนเดิลเพื่อตอบสนองต่อการเปลี่ยนแปลงของสัญญาณได้

เพิ่มกระดาษสีเมื่อไขปริศนาได้

ตอนนี้แอปใช้งานได้แล้ว คุณสามารถเพิ่มความสนุกด้วยการใส่กระดาษโปรยเมื่อไขปริศนาและถอดรหัสข้อความลับได้

หากต้องการเพิ่มกระดาษโปรย ให้ทำตามขั้นตอนต่อไปนี้ในความคิดเห็น 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 โดยมีข้อความที่ซ่อนอยู่ซึ่งถอดรหัสบนหน้าจอเพื่อสะกดคำว่า &quot;ถึงเวลาโปรยกระดาษสีแล้ว!&quot; และมีกระดาษสีโปรยออกมาเมื่อแก้ข้อความได้

7. ยินดีด้วย

ตอนนี้ Angular Cipher พร้อมที่จะถอดรหัสและแชร์ข้อความลับแล้ว หากมีข้อความสำหรับทีม Angular แท็กโซเชียลมีเดียของเราที่ @Angular เพื่อให้เราถอดรหัสได้ 🎉

เกม Angular Cypher ที่ไขได้ด้วยข้อความที่ซ่อนอยู่บนหน้าจอของ &quot;Angular Signals พร้อมให้ใช้งานในเวอร์ชันตัวอย่างสำหรับนักพัฒนาแอปใน v16 แล้ววันนี้&quot;

ตอนนี้คุณมี Reactive Primitive ใหม่ 3 รายการในกล่องเครื่องมือ Angular เพื่อลดความซับซ้อนในการพัฒนาและสร้างแอปได้เร็วขึ้นโดยค่าเริ่มต้น

ดูข้อมูลเพิ่มเติม

ลองใช้ Codelab เหล่านี้

อ่านเนื้อหาต่อไปนี้