1. قبل البدء
تقدّم "إشارات Angular " (Angular) ثلاثة أولية تفاعلية إلى الإصدار Angular الذي تعرفه وتحبه، ما يبسّط عملية التطوير ويساعدك في إنشاء تطبيقات أسرع بشكل تلقائي.
ما الذي ستنشئه
- ستتعرف على الأساسيات التفاعلية الثلاثة التي تم تقديمها مع الإشارات الزاوية:
signal()
وcomputed()
وeffect()
. - استخدِم ميزة Angular Signals لتعزيز أداء لعبة "الترميز الزاوي". الرموز هي أنظمة لتشفير البيانات وفك تشفيرها. في هذه اللعبة، يمكن للمستخدمين فك ترميز رسالة سرية عن طريق سحب الأدلة وإفلاتها لحل أحد الرموز وتخصيص الرسالة ومشاركة عنوان URL لإرسال رسائل سرية إلى الأصدقاء.
المتطلبات الأساسية
- الإلمام بخدمة 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" وظائف اللعبة.
للبدء، ما عليك سوى الاطّلاع على الإصدار النهائي لما ستنشئه: سايبر الإشارات الزاوية.
- اطّلِع على الرسالة المشفَّرة على الشاشة.
- اسحب زر حرف وأفلِته في لوحة المفاتيح للعمل على حل التشفير وفك ترميز الرسالة السرية.
- عند نجاح العملية، يمكنك الاطّلاع على كيفية تعديل الرسالة لفك ترميز المزيد من محتوى الرسالة السرية.
- انقر على تخصيص لتغيير المرسل والرسالة، ثم انقر على إنشاء & انسخ عنوان 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
لأزواج المفتاح/القيمة التي تم فك ترميزها بنجاح والتي ستُضيف إليها أثناء حلّ المشغّل للترميز.
من السمات الفريدة والفعّالة الفريدة لتصميم مكتبة إشارات 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
- Rethinking Reactivity with Signals (مؤتمر Google I/O لعام 2023)
- الميزات الجديدة في Angular (مؤتمر Google I/O لعام 2023)