Bắt đầu sử dụng Tín hiệu góc

1. Trước khi bắt đầu

Biểu trưng Angular màu đen

Angular Signals giới thiệu 3 thành phần phản ứng cơ bản cho Angular mà bạn quen thuộc và yêu thích, giúp đơn giản hoá quá trình phát triển và giúp bạn tạo các ứng dụng nhanh hơn theo mặc định.

Sản phẩm bạn sẽ tạo ra

  • Bạn sẽ tìm hiểu về 3 thành phần cơ bản phản ứng được giới thiệu cùng với Angular Signals: signal(), computed()effect().
  • Sử dụng Angular Signals để hỗ trợ trò chơi Angular Cipher. Mật mã là hệ thống mã hoá và giải mã dữ liệu. Trong trò chơi này, người dùng có thể giải mã một thông điệp bí mật bằng cách kéo và thả các manh mối để giải mật mã, tuỳ chỉnh thông điệp và chia sẻ URL để gửi thông điệp bí mật cho bạn bè.

Trò chơi Angular Cypher theo phong cách của một bảng điều khiển trò chơi màu xanh lục cổ điển, với một thông báo ẩn trên màn hình "Anqnxaa Lpcnaxl aaf pn jfafxyofa aofapfm pn a16 wyjak!"

Điều kiện tiên quyết

  • Có kiến thức về Angular và Typescript
  • Đề xuất: Xem video Rethinking Reactivity with Signals (Tư duy lại về tính phản ứng bằng tín hiệu) để tìm hiểu về thư viện Angular Signals

2. Lấy mã

Mọi thứ bạn cần cho dự án này đều có trong Stackblitz. Stackblitz là phương thức được đề xuất để tham gia lớp học lập trình này. Ngoài ra, bạn có thể sao chép mã và mở mã đó trong môi trường phát triển mà bạn yêu thích.

Mở Stackblitz và chạy ứng dụng

Để bắt đầu, hãy mở đường liên kết Stackblitz trong trình duyệt web mà bạn yêu thích:

  1. Mở một thẻ trình duyệt mới rồi truy cập vào https://stackblitz.com/edit/io-signals-codelab-starter?file=src%2Fcipher%2Fservice.cipher.ts,src%2Fsecret-message%2Fservice.message.ts&service.massage.ts
  2. Phân nhánh Stackblitz để tạo không gian làm việc có thể chỉnh sửa của riêng bạn. Stackblitz sẽ tự động chạy ứng dụng và bạn đã sẵn sàng!

Cách khác: Sao chép kho lưu trữ và phân phát ứng dụng

Sử dụng VSCode hoặc một IDE cục bộ là một phương pháp thay thế để hoàn thành lớp học lập trình này:

  1. Mở một thẻ trình duyệt mới rồi truy cập vào https://github.com/angular/codelabs/tree/signals-get-started.
  2. Phân nhánh và sao chép kho lưu trữ, rồi dùng lệnh cd codelabs/ để chuyển vào kho lưu trữ.
  3. Kiểm tra nhánh mã khởi đầu bằng lệnh git checkout signals-get-started.
  4. Mở mã trong VSCode hoặc IDE mà bạn muốn.
  5. Để cài đặt các phần phụ thuộc cần thiết để chạy máy chủ, hãy dùng lệnh npm install.
  6. Để chạy máy chủ, hãy dùng lệnh ng serve.
  7. Mở một thẻ trình duyệt đến http://localhost:4200.

3. Thiết lập đường cơ sở

Điểm xuất phát của bạn là một trò chơi Angular Cipher nhưng trò chơi này chưa hoạt động. Angular Signals sẽ hỗ trợ chức năng của trò chơi.

Trò chơi Angular Cypher theo phong cách của một bảng điều khiển trò chơi màu xanh lục cổ điển, với một thông báo ẩn trên màn hình "Anqnxaa Lpcnaxl aaf pn jfafxyofa aofapfm pn a16 wyjak!"

Để bắt đầu, hãy xem phiên bản hoàn chỉnh của những gì bạn sẽ xây dựng: Angular Signals Cypher.

  1. Xem thông báo được mã hoá trên màn hình.
  2. Kéo và thả nút chữ cái trong bàn phím để giải mật mã và giải mã thông điệp bí mật.
  3. Khi thành công, hãy xem cách thông báo cập nhật để giải mã thêm thông tin về thông báo bí mật.
  4. Nhấp vào Tuỳ chỉnh để thay đổi Người gửi và Thông báo, sau đó nhấp vào Tạo và sao chép URL để xem các giá trị trên màn hình và thay đổi URL.
  5. Mẹo hay: Sao chép và dán URL vào một thẻ mới hoặc chia sẻ với bạn bè để xem người gửi và tin nhắn được lưu trữ trong URL như thế nào.

Ảnh GIF về trò chơi Angular Cypher, trong đó một thông báo ẩn đang được giải mã trên màn hình để tạo thành dòng chữ "Angular Signals hiện đang ở giai đoạn xem trước dành cho nhà phát triển trong phiên bản 16!"

4. Xác định signal() đầu tiên của bạn

Tín hiệu là một giá trị có thể cho Angular biết thời điểm giá trị đó thay đổi. Một số tín hiệu có thể được thay đổi trực tiếp, trong khi những tín hiệu khác tính toán giá trị của chúng từ giá trị của các tín hiệu khác. Các tín hiệu cùng nhau tạo ra một biểu đồ có hướng về các phần phụ thuộc, mô hình hoá cách dữ liệu truyền trong ứng dụng của bạn.

Angular có thể sử dụng thông báo từ các tín hiệu để biết những thành phần nào cần được phát hiện thay đổi hoặc thực thi các hàm hiệu ứng mà bạn xác định.

Chuyển đổi superSecretMessage thành signal()

superSecretMessage là một giá trị trong MessageService, xác định thông điệp bí mật mà người chơi giải mã. Hiện tại, giá trị này không thông báo cho ứng dụng về các thay đổi, vì vậy nút Customize (Tuỳ chỉnh) không hoạt động. Bạn có thể giải quyết vấn đề này bằng một tín hiệu.

Bằng cách tạo superSecretMessage thành một tín hiệu, bạn có thể thông báo cho những phần của ứng dụng phụ thuộc vào việc biết thời điểm thông báo đã thay đổi. Khi tuỳ chỉnh thông báo trong một hộp thoại, bạn sẽ đặt tín hiệu để cập nhật phần còn lại của ứng dụng bằng thông báo mới.

Để xác định tín hiệu đầu tiên, hãy thực hiện các bước sau trong phần nhận xét TODO(1): Define your first signal() trong mỗi tệp:

  1. Trong tệp service.message.ts, hãy dùng thư viện Signals để tạo superSecretMessage phản ứng:

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

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

Thao tác này sẽ tự động nhắc bạn nhập signal từ @angular/core. Nếu làm mới trang, bạn có thể sẽ gặp phải lỗi ở những nơi trước đây bạn đã đề cập đến superSecretMessage. Nguyên nhân là do bạn đã thay đổi loại superSecretMessage từ string thành SettableSignal<string>. Bạn có thể khắc phục vấn đề này bằng cách thay đổi tất cả các tham chiếu của superSecretMessage để sử dụng Signals API. Bất cứ khi nào bạn đọc giá trị, hãy gọi phương thức getter Signal superSecretMessage(). Và bất cứ khi nào bạn ghi giá trị, hãy sử dụng API .set trên SettableSignal để đặt giá trị mới cho thông báo.

  1. Trong các tệp secret-message.tsservice.message.ts, hãy cập nhật tất cả các tham chiếu của superSecretMessage thành 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()

Khám phá 2 tín hiệu còn lại

  • Lưu ý rằng bạn có 2 tín hiệu khác trong ứng dụng:

src/app/cipher/service.cipher.ts

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

CipherService xác định tín hiệu cipher, một mối liên kết được tạo ngẫu nhiên giữa các cặp khoá-giá trị của một chữ cái trong bảng chữ cái với một chữ cái cipher mới. Bạn dùng thông tin này để xáo trộn thông báo và xác định xem người chơi có tìm được kết quả khớp thành công trên bàn phím hay không.

Bạn cũng có tín hiệu decodedCipher về các cặp khoá-giá trị đã được giải mã thành công mà bạn sẽ thêm vào khi người chơi giải được mật mã.

Một thuộc tính độc đáo và mạnh mẽ trong thiết kế thư viện Tín hiệu của Angular là bạn có thể giới thiệu tính phản ứng ở mọi nơi. Bạn chỉ cần xác định tín hiệu một lần trong các dịch vụ của ứng dụng và có thể sử dụng tín hiệu đó trong một mẫu, thành phần, đường ống, các dịch vụ khác hoặc bất kỳ nơi nào bạn có thể viết mã xử lý ứng dụng. Chúng không bị giới hạn hoặc ràng buộc với phạm vi thành phần.

Xác minh thay đổi

  • Bạn cần thực hiện thêm một bước nữa thì ứng dụng mới hoạt động. Hiện tại, hãy thử thêm một console.log() vào các phần khác nhau trong ứng dụng để xem superSecretMessage mới của bạn được đặt như thế nào.

Stackblitz có thông báo console.log() cho thấy superSecretMessage đang ghi nhật ký chính xác thông báo mới.

5. Xác định computed() đầu tiên

Trong nhiều trường hợp, bạn có thể thấy mình đang lấy trạng thái từ các giá trị hiện có. Bạn nên cập nhật trạng thái phái sinh khi giá trị phụ thuộc thay đổi.

Với computed(), bạn có thể khai báo một tín hiệu lấy giá trị từ các tín hiệu khác.

Chuyển đổi solvedMessage thành computed()

solvedMessage dịch giá trị secretMessage từ mã hoá sang giải mã bằng tín hiệu decodedCipher.

Điều này rất hữu ích vì bạn có thể thấy mình đang lấy một giá trị được tính toán dựa trên một giá trị được tính toán khác. Vì vậy, bất cứ khi nào một tín hiệu trong ngữ cảnh phản ứng được liên kết đó thay đổi, các phần phụ thuộc sẽ được thông báo.

Hiện tại, solvedMessage sẽ không được cập nhật khi bạn thay đổi secretMessage, decodedCipher hoặc superSecretMessage. Vì vậy, bạn sẽ không thấy nội dung cập nhật trên màn hình khi người chơi giải được mật mã.

Bằng cách tạo solvedMessage được tính toán, bạn sẽ tạo một bối cảnh phản ứng để khi cập nhật thông báo hoặc giải thuật toán mật mã, bạn có thể lấy được thông tin cập nhật trạng thái từ các phần phụ thuộc được theo dõi.

Để chuyển đổi solvedMessage thành computed(), hãy thực hiện các bước sau trong phần nhận xét TODO(2): Define your first computed() trong mỗi tệp:

  1. Trong tệp service.message.ts, hãy dùng thư viện Signals để tạo solvedMessage phản ứng:

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

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

Thao tác này sẽ tự động nhắc bạn nhập computed từ @angular/core. Nếu làm mới trang, bạn có thể sẽ gặp phải lỗi ở những nơi trước đây bạn đã đề cập đến solvedMessage. Nguyên nhân là do bạn đã thay đổi loại của superSecretMessage từ string thành Signal<string>, một hàm. Bạn có thể khắc phục bằng cách thay đổi tất cả các tham chiếu của solvedMessage thành solvedMessage().

  1. Trong tệp secret-message.ts, hãy cập nhật tất cả các tham chiếu của solvedMessage thành 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>

Xin lưu ý rằng không giống như superSecretMessage, solvedMessage không phải là SettableSignal – bạn không thể thay đổi trực tiếp giá trị của solvedMessage. Thay vào đó, giá trị của thành phần này sẽ luôn được cập nhật bất cứ khi nào một trong các tín hiệu phụ thuộc của thành phần này (secretMessagedecodedCipher) được cập nhật.

Khám phá 2 computed() hàm khác

  • Xin lưu ý rằng bạn có 2 giá trị được tính khác trong ứng dụng:

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 xác định một secretMessage được tính toán, superSecretMessage được mã hoá bằng cipher mà người chơi phải giải.

CipherService xác định một unsolvedAlphabet được tính toán, một danh sách tất cả các chữ cái mà người chơi chưa giải được, được lấy từ danh sách các khoá mật mã đã giải trong decodedCipher.

Xác minh thay đổi

Giờ đây, superSecretMessage là một tín hiệu và solvedMessage là một giá trị được tính toán, ứng dụng sẽ hoạt động! Kiểm thử các chức năng của trò chơi:

  1. Kéo và thả một LetterGuessComponent vào một LetterKeyComponent trong CipherComponent của bạn để giải mã và giải mã thông điệp bí mật.
  2. Xem cách SecretMessageComponent cập nhật khi bạn giải mã thêm nội dung của thông điệp bí mật.
  3. Nhấp vào Tuỳ chỉnh để thay đổi Người gửi và Thông báo, sau đó nhấp vào Tạo và sao chép URL để xem các giá trị trên màn hình và thay đổi URL.
  4. Mẹo hay: Sao chép và dán URL vào một thẻ mới hoặc chia sẻ với bạn bè để xem người gửi và tin nhắn được lưu trữ trong URL như thế nào.

Ảnh GIF về trò chơi Angular Cypher, trong đó một thông báo ẩn đang được giải mã trên màn hình để tạo thành dòng chữ &quot;Angular Signals hiện đang ở giai đoạn xem trước dành cho nhà phát triển trong phiên bản 16!&quot;

6. Thêm effect() đầu tiên

Đôi khi, bạn có thể muốn một điều gì đó xảy ra khi một tín hiệu có giá trị mới. Với effect(), bạn có thể lên lịch và chạy một hàm trình xử lý để phản hồi các tín hiệu thay đổi.

Thêm hiệu ứng giấy confetti khi mật mã được giải

Giờ đây, khi ứng dụng đã hoạt động, bạn có thể thêm một chút thú vị bằng cách thêm hiệu ứng giấy confetti khi thuật toán mật mã được giải và thông báo bí mật được giải mã.

Để thêm hiệu ứng giấy confetti, hãy thực hiện các bước sau trong phần nhận xét TODO(3): Add your first effect():

  1. Trong tệp cipher.ts, hãy lên lịch cho một hiệu ứng để thêm hoa giấy khi thông báo được giải mã:

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

Lưu ý rằng hiệu ứng này phụ thuộc vào một tín hiệu và một giá trị được tính toán: this.messages.superSecretMessage()this.messages.solvedMessage().

Effect giúp bạn lên lịch cho hàm confetti trong một bối cảnh phản ứng để theo dõi và đánh giá lại khi các phần phụ thuộc của hàm này được cập nhật.

Xác minh thay đổi

  • Hãy thử giải thuật toán mật mã (gợi ý: bạn có thể thay đổi thông báo thành một thông báo ngắn để kiểm thử nhanh hơn!). Một thông báo chúc mừng bằng hoa giấy sẽ xuất hiện khi bạn đạt được effect() đầu tiên!

Ảnh GIF về trò chơi Angular Cypher, trong đó một thông điệp ẩn đang được giải mã trên màn hình để đánh vần &quot;Confetti time!&quot; (Đã đến lúc bắn hoa giấy!) và pháo hoa giấy nổ khi thông điệp được giải.

7. Xin chúc mừng!

Giờ đây, thuật toán mật mã Angular của bạn đã sẵn sàng giải mã và chia sẻ các thông điệp bí mật! Bạn có thông điệp muốn gửi cho Nhóm Angular? Hãy gắn thẻ mạng xã hội của chúng tôi tại @Angular để chúng tôi có thể giải mã! 🎉

Trò chơi Angular Cypher được giải bằng một thông báo ẩn trên màn hình &quot;Angular Signals hiện đang ở bản xem trước dành cho nhà phát triển trong phiên bản 16!&quot;

Giờ đây, bạn có 3 thành phần cơ bản phản ứng mới trong hộp công cụ Angular để đơn giản hoá quá trình phát triển và tạo ứng dụng nhanh hơn theo mặc định.

Tìm hiểu thêm

Hãy xem các lớp học lập trình sau:

Đọc các tài liệu sau: