1. قبل البدء
تقدّم "إشارات Angular " (Angular) ثلاثة أولية تفاعلية إلى الإصدار Angular الذي تعرفه وتحبه، ما يبسّط عملية التطوير ويساعدك في إنشاء تطبيقات أسرع بشكل تلقائي.
ما الذي ستنشئه
- يمكنك التعرّف على العناصر الأساسية الثلاث للتفاعل التي تم تقديمها مع Angular Signals:
signal()
وcomputed()
وeffect()
. - استخدِم إشارات Angular لتشغيل لعبة Angular Cipher. التشفير هو أنظمة لتشفير البيانات وفك تشفيرها. في هذه اللعبة، يمكن للمستخدمين فك تشفير رسالة سرية من خلال سحب القرائن وإفلاتها لحلّ أحد التشفيرات، وتخصيص الرسالة، ومشاركة عنوان URL لإرسال رسائل سرية إلى الأصدقاء.
المتطلبات الأساسية
- معرفة Angular وTypescript
- يُنصح بمشاهدة إعادة النظر في الاستجابة باستخدام الإشارات للتعرّف على مكتبة 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 أو بيئة تطوير البرامج المتكاملة المفضّلة لديك.
- لتثبيت التبعيات المطلوبة لتشغيل الخادم، استخدِم الأمر
npm install
. - لتشغيل الخادم، استخدِم الأمر
ng serve
. - افتح علامة تبويب في المتصفّح للانتقال إلى http://localhost:4200.
3- تحديد مرجع
نقطة البداية هي لعبة Angular Cipher، ولكنها لا تعمل بعد. ستعزّز "إشارات Angular" وظائف اللعبة.
للبدء، اطّلِع على النسخة النهائية من العنصر الذي ستُنشئه: Angular Signals Cypher.
- اطّلِع على الرسالة المشفَّرة على الشاشة.
- اسحب زر حرف وأفلِته في لوحة المفاتيح للمساعدة في حلّ الشفرة وفك ترميز الرسالة السرية.
- عند نجاح العملية، يمكنك الاطّلاع على كيفية تعديل الرسالة لفك ترميز المزيد من الرسالة السرية.
- انقر على تخصيص لتغيير المُرسِل والرسالة، ثم انقر على إنشاء عنوان URL ونسخه للاطّلاع على القيم على الشاشة وتغيير عنوان URL.
- ميزة إضافية: يمكنك نسخ عنوان URL ولصقه في علامة تبويب جديدة أو مشاركته مع صديق، والاطّلاع على كيفية تخزين المُرسِل والرسالة في عنوان URL.
4. حدِّد إشارة() الأولى.
الإشارة هي قيمة يمكنها إخبار Angular عندما تتغيّر. يمكن تغيير بعض الإشارات مباشرةً، في حين تحسب الإشارات الأخرى قيمها من قيم إشارات أخرى. معًا، تنشئ الإشارات رسمًا بيانيًا موجهًا للتبعيات التي تنمّذ كيفية تدفق البيانات في تطبيقك.
يمكن أن تستخدم Angular الإشعارات الواردة من الإشارات لمعرفة المكونات التي يجب رصد التغييرات فيها أو تنفيذ دوال التأثير التي تحدّدها.
تحويل superSecretMessage
إلى signal()
superSecretMessage
هي قيمة في MessageService
تحدد الرسالة السرية التي يفكّها المشغّل. في الوقت الحالي، لا تُرسِل القيمة إشعارًا إلى التطبيق بالتغييرات، لذا لا يعمل الزر تخصيص. يمكنك حلّ هذه المشكلة باستخدام إشارة.
من خلال جعل superSecretMessage
إشارة، يمكنك إرسال إشعار إلى أجزاء من التطبيق تعتمد على معرفة وقت تغيُّر الرسالة. عند تخصيص الرسالة في مربّع حوار، يمكنك ضبط الإشارة لتعديل بقية التطبيق بالرسالة الجديدة.
لتحديد إشارة التحذير الأولى، عليك اتّباع الخطوات التالية ضمن التعليق TODO(1): Define your first signal()
في كل ملف:
- في ملف
service.message.ts
، استخدِم مكتبة "الإشارات" لجعل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
على SettableSignal
لضبط القيمة الجديدة للرسالة.
- في الملفَين
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
الجديد.
5- تحديد أول حوسبة()
في العديد من الحالات، قد تحتاج إلى اشتقاق الحالة من القيم الحالية. من الأفضل تعديل الحالة المستمدة عند تغيير القيمة التابعة.
باستخدام computed()
، يمكنك التعبير بشكل صريح عن إشارة تستمدّ قيمتها من إشارات أخرى.
تحويل solvedMessage
إلى computed()
يُحوّل solvedMessage
قيمة secretMessage
من الترميز إلى فك الترميز باستخدام إشارة decodedCipher
.
وهذا أمر رائع للغاية لأنّه يمكنك الاطّلاع على أنّك تستخرج قيمة محسوبة استنادًا إلى قيمة محسوبة أخرى، لذا في أي وقت يتغيّر فيه إشارة ضمن السياق التفاعلي المرتبط، يتم إرسال إشعار إلى العناصر التابعة.
في الوقت الحالي، لا يتم تعديل solvedMessage
عند تغيير secretMessage
أو decodedCipher
أو superSecretMessage
. وبالتالي، لن تظهر لك أي تعديلات على الشاشة عندما يحلّ اللاعب الشفرة.
من خلال جعل solvedMessage
محسوبة، يمكنك إنشاء سياق تفاعلي بحيث يمكنك اشتقاق تعديل الحالة من التبعيات التي يتم تتبُّعها عند تعديل الرسالة أو حلّ التشفير.
لتحويل solvedMessage
إلى computed()
، نفِّذ الخطوات التالية ضمن التعليق TODO(2): Define your first computed()
في كل ملف:
- في ملف
service.message.ts
، استخدِم مكتبة "الإشارات" لجعل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()
.
- في ملف
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
قيمة محسوبة، من المفترض أن يعمل التطبيق. اختبِر وظائف اللعبة:
- اسحب
LetterGuessComponent
وأفلِته فيLetterKeyComponent
فيCipherComponent
للمساعدة في حلّ الشفرة وفك ترميز الرسالة السرية. - اطّلِع على كيفية تعديل
SecretMessageComponent
أثناء فك ترميز المزيد من الرسالة السرية. - انقر على تخصيص لتغيير "المُرسِل والرسالة"، ثم انقر على إنشاء عنوان URL ونسخه للاطّلاع على القيم التي تظهر على الشاشة وتغيير عنوان URL.
- ميزة إضافية: يمكنك نسخ عنوان URL ولصقه في علامة تبويب جديدة أو مشاركته مع صديق، والاطّلاع على كيفية تخزين المُرسِل والرسالة في عنوان URL.
6- أضِف التأثير الأول()
قد تحتاج أحيانًا إلى تنفيذ إجراء عندما تتغيّر قيمة إشارة معيّنة. باستخدام "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()
لك.
7- تهانينا!
أصبحت ميزة Angular Cipher جاهزة الآن لفك ترميز الرسائل السرية ومشاركتها. هل لديك رسالة إلى فريق Angular؟ يمكنك الإشارة إلى حسابنا على وسائل التواصل الاجتماعي @Angular لنتمكّن من فك ترميزه. 🎉
لديك الآن ثلاث عناصر أساسية جديدة للتفاعل في مجموعة أدوات Angular لتبسيط عملية التطوير وإنشاء تطبيقات أسرع بشكلٍ تلقائي.
مزيد من المعلومات
اطّلِع على الدروس التطبيقية التالية حول الترميز:
اطّلِع على هذه المواد:
- Angular.io
- إعادة النظر في الاستجابة باستخدام الإشارات (مؤتمر Google I/O لعام 2023)
- الميزات الجديدة في Angular (مؤتمر Google I/O لعام 2023)