| معيار المقارنة البرمجية | المدخلات التقليدية (@Input decorator) | مدخلات الإشارات الحديثة (input API) |
|---|---|---|
| طبيعة المتجر الداخلي | خاصية عادية تتطلب ngOnChanges لرصد تغيراتها | إشارة فعلية (Signal) يتم قراءتها كدالة () |
| التعامل مع القيم المطلوبة | تتطلب أحياناً تحققاً يدوياً أو استخدام علامة التعجب (!) | تدعم الخصائص الإلزامية بكل سهولة عبر input.required<T>() |
| التكامل مع الإشارات المحسوبة | منفصلة وتحتاج لإعداد إضافي لربطها بالـ Computed Signals | متكاملة تماماً وفورية مع الـ computed والـ effect |
| أداء رصد التغيرات (Change Detection) | تعتمد على دورة حياة المكون التقليدية والتحقق العام | تحدث الواجهة بدقة متناهية وفورية على مستوى العنصر المتغير فقط |
ننتقل في هذا الدرس الثالث من الفصل السابع إلى إحدى أهم النقلات النوعية في إصدار Angular 22.1، ألا وهي استقبال البيانات المعتمدة على الإشارات (Signal Inputs). لقد غيرت دالة input() الحديثة طريقة استقبال البيانات من المكونات الأب جذرياً، حيث تحولت المدخلات من خصائص تقليدية صامتة إلى إشارات حقيقية قابلة للقراءة (Read-only Signals)، مما يتيح تكاملاً خارقاً مع الإشارات المحسوبة والآثار، ويوفر أداءً استثنائياً في رصد وتحديث الواجهات
عند تعريف مدخل باستخدام input<T>()، فإن القيمة المستقبلة تصبح إشارة. هذا يعني أنك لقراءتها داخل صنف المكون أو القالب، يجب أن تستخدمها كدالة (this.myInput())، مما يطلع أنجولر فوراً على أن هذا المكون يعتمد على هذه القيمة.
يوفر النظام الحديث صيغتين رئيسيتين: input<T>(defaultValue) للقيم الاختيارية ذات القيمة الافتراضية، و input.required<T>() للمدخلات الإلزامية التي يضمن النظام توفرها وقت الترجمة والتشغيل، مما يمنع الأخطاء البرمجية كلياً.
| 1 | import { Component, input, computed } from '@angular/core'; |
| 2 | |
| 3 | @Component({ |
| 4 | selector: 'app-product-signal-card', |
| 5 | standalone: true, |
| 6 | templateUrl: './product-signal-card.component.html', |
| 7 | styleUrl: './product-signal-card.component.css' |
| 8 | }) |
| 9 | export class ProductSignalCardComponent { |
| 10 | // مدخل اختياري بقيمة افتراضية |
| 11 | productTitle = input<string>('منتج افتراضي'); |
| 12 | |
| 13 | // مدخل إلزامي حديث لا يقبل القسمة على عدم التواجد |
| 14 | productPrice = input.required<number>(); |
| 15 | |
| 16 | // إشارة محسوبة تعتمد على مدخل الإشارات مباشرة لتوليد قيمة مشتقة |
| 17 | formattedPriceInfo = computed(() => { |
| 18 | return `السعر الكلي مع الضريبة: ${this.productPrice() * 1.15} ريال`; |
| 19 | }); |
| 20 | } |
| 1 | <div class="signal-card"> |
| 2 | <h4>عرض بيانات المنتج بالإشارات الحديثة</h4> |
| 3 | <p>اسم المنتج: <strong>{{ productTitle() }}</strong></p> |
| 4 | <p>السعر الأساسي: <strong>{{ productPrice() }}</strong></p> |
| 5 | <p class="tax-info">{{ formattedPriceInfo() }}</p> |
| 6 | </div> |
| 1 | .signal-card { |
| 2 | background: #0f172a; |
| 3 | color: #f8fafc; |
| 4 | padding: 18px; |
| 5 | border-radius: 10px; |
| 6 | border: 1px solid #38bdf8; |
| 7 | margin-top: 12px; |
| 8 | } |
| 9 | |
| 10 | .tax-info { |
| 11 | color: #38bdf8; |
| 12 | font-weight: bold; |
| 13 | background: #1e293b; |
| 14 | padding: 8px; |
| 15 | border-radius: 6px; |
| 16 | margin-top: 8px; |
| 17 | } |