1. 事前準備
Angular Signals 為您熟悉喜愛的 Angular 引進三種反應式原始元素,簡化開發作業,並預設加快應用程式建構速度。
建構項目
- 您將瞭解 Angular 訊號引進的三種回應原始元素:
signal()
、computed()
和effect()
。 - 使用 Angular 信號為 Angular Cipher 遊戲提供動力。密碼是用於加密及解密資料的系統。在這個遊戲中,使用者可以拖曳並放置線索來解開密碼,然後自訂訊息並分享網址,將密碼訊息傳送給朋友。
必要條件
- 熟悉 Angular 和 TypeScript
- 建議:觀看「Rethinking Reactivity with Signals」,瞭解 Angular Signals 程式庫
2. 取得程式碼
這個專案所需的一切都包含在 Stackblitz 中。建議您使用 Stackblitz 完成本程式碼研究室的課程。或者,您也可以複製程式碼,並在喜愛的開發環境中開啟。
開啟 Stackblitz 並執行應用程式
如要開始使用,請在您慣用的網路瀏覽器中開啟 Stackblitz 連結:
- 開啟新的瀏覽器分頁,然後前往 https://stackblitz.com/edit/io-signals-codelab-starter?file=src%2Fcipher%2Fservice.cipher.ts,src%2Fsecret-message%2Fservice.message.ts&service.massage.ts
- 使用 Stackblitz 建立自己的可編輯工作區。Stackblitz 應會自動執行應用程式,您就可以開始使用了!
替代做法:複製存放區並提供應用程式服務
使用 VSCode 或本機 IDE 是執行本程式碼研究室的替代方法:
- 開啟新的瀏覽器分頁,然後前往 https://github.com/angular/codelabs/tree/signals-get-started。
- 建立分支並複製存放區,並使用
cd codelabs/
指令來移至存放區。 - 查看包含
git checkout signals-get-started
指令的範例程式碼分支。 - 在 VSCode 或您偏好的 IDE 中開啟程式碼。
- 如要安裝執行伺服器所需的依附元件,請使用
npm install
指令。 - 如要執行伺服器,請使用
ng serve
指令。 - 開啟瀏覽器分頁並前往 http://localhost:4200。
3. 建立基準
您的起點是 Angular Cipher 遊戲,但目前尚未運作。Angular 信號可協助遊戲功能。
首先,請逐步瞭解即將建構產品的完成版本:Angular Signals Cypher。
- 查看畫面上的密碼訊息。
- 在鍵盤中拖曳並放置字母按鈕,以解開密碼並解碼秘密訊息。
- 成功後,請查看訊息如何更新,以便解碼更多機密訊息。
- 按一下 [自訂] 變更寄件者和訊息,然後按一下「建立及複製網址」,即可查看畫面上的值和網址的變更。
- 額外資訊:複製網址並貼到新分頁,或與朋友分享,看看網址中儲存了哪些寄件者和訊息。
4. 定義第一個 signal()
信號是一種值,可在 Angular 變動時通知對方。有些信號可以直接變更,有些則會根據其他信號的值計算值。信號會共同建立依附性圖表,藉此模擬資料在應用程式中流動的方式。
Angular 可使用信號傳送的通知,瞭解需要偵測變更的元件,或執行您定義的 effect 函式。
將 superSecretMessage
轉換為 signal()
superSecretMessage
是 MessageService
中的值,用於定義玩家解碼的密件。目前,該值不會通知應用程式變更,因此「自訂」按鈕無法正常運作。你可以透過信號解決這個問題。
將 superSecretMessage
設為訊號,即可通知應用程式部分依據訊息變更時間。在對話方塊中自訂訊息時,您會設定信號,以便使用新訊息更新應用程式的其餘部分。
如要定義第一個信號,請在每個檔案的 TODO(1): Define your first signal()
註解下方執行下列步驟:
- 在
service.message.ts
檔案中,使用 Signals 程式庫讓superSecretMessage
具備回應性:
src/app/secret-message/service.message.ts
superSecretMessage = signal(
'Angular Signals are in developer preview in v16 today!'
);
系統會自動提示您從 @angular/core
匯入 signal
。如果重新整理頁面,您可能會在先前參照 superSecretMessage
的部分遇到錯誤。這是因為您已將 superSecretMessage
的類型從 string
變更為 SettableSignal<string>
。您可以將 superSecretMessage
的所有參照變更為 Signals API,藉此修正此問題。無論您在何處讀取值,都必須呼叫 Signal getter superSecretMessage()
。無論您在何處寫入值,請在 SettableSignal
上使用 .set
API,為訊息設定新值。
- 在
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
如何設定。
5. 定義第一個 computed()
在許多情況下,您可能會從現有值衍生狀態。在相依值變更時,最好更新衍生狀態。
使用 computed()
,即可透過宣告方式表示從其他信號衍生價值的信號。
將 solvedMessage
轉換為 computed()
solvedMessage
會使用 decodedCipher
信號,轉換編碼為已解碼的 secretMessage
值。
這點特別有趣,因為您可以看到自己是根據另一個計算結果衍生出計算結果,因此只要對應的回應式內容變更,就會通知相關依附元件。
目前,變更 secretMessage
、decodedCipher
或 superSecretMessage
時,solvedMessage
不會更新。因此,當玩家破解密碼時,您不會看到畫面更新。
計算 solvedMessage
即可建立回應式結構定義,以便在更新訊息或解決加密作業時,從已追蹤的依附元件衍生狀態更新。
如要將 solvedMessage
轉換為 computed()
,請在每個檔案的 TODO(2): Define your first computed()
註解下方執行下列步驟:
- 在
service.message.ts
檔案中,使用 Signals 程式庫讓solvedMessage
具備回應性:
src/app/secret-message/service.message.ts
solvedMessage = computed(() =>
this.translateMessage(
this.secretMessage(),
this.cipher.decodedCipher()
)
);
系統會自動提示您從 @angular/core
匯入 computed
。如果重新整理頁面,您可能會在先前參照 solvedMessage
的部分遇到錯誤。這是因為您已將 superSecretMessage
的類型從 string
變更為 Signal<string>
(函式)。如要修正這個問題,請將 solvedMessage
的所有參照變更為 solvedMessage()
。
- 在
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
與 superSecretMessage
不同,它不是 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
(由玩家設法解決的 cipher
編碼) superSecretMessage
。
CipherService
會定義 unsolvedAlphabet
計算結果,也就是玩家尚未解開的所有字母清單,這會從 decodedCipher
中已解開的密碼金鑰清單衍生而來。
驗證變更
superSecretMessage
是信號,solvedMessage
是計算值,因此應用程式應該可以正常運作!測試遊戲功能:
- 將
LetterGuessComponent
拖曳到CipherComponent
中的LetterKeyComponent
,即可解析密鑰並解碼密鑰。 - 瞭解隨著您解碼更多密件內容時,
SecretMessageComponent
如何更新。 - 按一下「自訂」變更「寄件者」和「訊息」,然後按一下「建立並複製網址」,查看畫面上的值和網址變更。
- 額外資訊:複製網址並貼到新分頁,或與朋友分享,看看網址中儲存了哪些寄件者和訊息。
6. 新增第一個 effect()
有時,您可能會想在信號有新值時發生某些情況。使用 effect()
時,您可以根據信號變更的情況,安排及執行處理常式函式。
在解開密碼時加入灑紙
應用程式現在已可正常運作,您可以新增一些有趣的效果,例如在解開密碼並解碼秘密訊息時顯示灑紙。
如要新增灑紙花特效,請在 TODO(3): Add your first effect()
註解下方執行下列步驟:
- 在
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 可協助您在回應式內容中排程灑紙花函式,以便追蹤並重新評估依附元件更新的時間。
驗證變更
- 請試著解開加密方式 (提示:將訊息改成更精簡的內容,即可更快進行測試!)。系統會顯示彩色紙碎屑圖案,恭喜你獲得第一個
effect()
!
7. 恭喜!
Angular Cipher 現已準備好解碼及分享機密訊息!想傳送訊息給 Angular 團隊嗎?請標記我們的社群媒體帳號 @Angular,方便我們解碼!🎉
Angular 工具箱現在提供三個新的回應原始元素,可簡化開發作業,並預設加快應用程式建構速度。
瞭解詳情
請查看下列程式碼研究室:
請參閱下列資料:
- Angular.io
- Rethinking Reactivity with Signals (Google I/O 2023)
- Angular 新功能 (2023 年 Google I/O 大會)