| وجه المقارنة المعمارية | الحالة المحلية للمكون (Local State) | الحالة العامة للتطبيق (Global State) |
|---|---|---|
| نطاق المشاركة والوصول | محدود داخل المكون المعني وشجيرته الفرعية المباشرة فقط | متاح ومشارك لجميع المكونات والشاشات عبر التطبيق بالكامل |
| دورة الحياة والتدمير | تتولد مع إنشاء المكون وتُدمر تلقائياً وفوراً عند تدميره | تبقى حية وفعالة طوال فترة تشغيل التطبيق بالكامل (Singleton) |
| تعقيد الإدارة والصيانة | منخفض وبسيط للغاية، لا يتطلب بنى تحتية معقدة | أعلى نسبياً ويتطلب تخطيطاً هندسيماً دقيقاً لتفادي التداخلات غير المرغوبة |
في معمارية Angular 22.1 الحديثة، يمثل اتخاذ القرار بشأن مكان تمركز وتخزين الحالة (State Location) مفتاحاً أساسياً لنجاح أو فشل تصميم التطبيق. الفهم الهندسي للحدود الفاصلة بين الحالة المحلية الخاصة بمكون معين (Local State) وتلك التي تتطلب نطاقاً عاماً يشترك فيه النظام (Global State) يمنع تعقيد الأكواد ويسهم في الحفاظ على أداء عالٍ واستهلاك مثالي للذاكرة دون تداخل غير مبرر.
قاعدة العمارة البرمجية النظيفة تنص على أن تبدأ الحالة دائماً في أدنى مستوى ممكن (محلياً داخل المكون). لا ترفع أي حالة إلى النطاق العام إلا إذا كانت مطلوبة فعلياً من قبل مكونات أخرى متباعدة في شجرة المكونات.
وضع كل شيء في المتجر العام يخلق اقترانًا شديدًا (Tight Coupling) بين أجزاء التطبيق، مما يصعب عملية اختبار المكونات بمعزل عن بقية النظام ويستهلك موارد الذاكرة بلا داعٍ.
| 1 | import { Component, signal } from '@angular/core'; |
| 2 | import { CommonModule } from '@angular/common'; |
| 3 | |
| 4 | @Component({ |
| 5 | selector: 'app-local-counter', |
| 6 | standalone: true, |
| 7 | imports: [CommonModule], |
| 8 | template: ` |
| 9 | <div class="local-box"> |
| 10 | <h4>حالة محلية بحتة (Local State)</h4> |
| 11 | <p>القيمة الحالية: <strong>{{ count() }}</strong></p> |
| 12 | <button (click)="increment()">زيادة العداد المحلي</button> |
| 13 | </div> |
| 14 | `, |
| 15 | styles: [` |
| 16 | .local-box { background: #090d16; color: #fff; padding: 16px; border-radius: 8px; border: 1px solid #334155; } |
| 17 | button { background: #38bdf8; color: #090d16; border: none; padding: 8px 16px; border-radius: 4px; font-weight: bold; cursor: pointer; } |
| 18 | `] |
| 19 | }) |
| 20 | export class LocalCounterComponent { |
| 21 | // حالة محلية تعيش وتموت مع هذا المكون فقط |
| 22 | readonly count = signal(0); |
| 23 | |
| 24 | increment() { |
| 25 | this.count.update(c => c + 1); |
| 26 | } |
| 27 | } |
⚠️ تحذير
تجنب رفع حالات المكونات المؤقتة إلى النطاق العام! تخزين حالات تفاعلية مؤقتة (مثل حالة فتح وغلق قائمة منسدلة، أو إدخال نصي مؤقت في نموذج فرعي) داخل المتجر العام يعد خطأً معمارياً فادحاً يستهلك الذاكرة ويسبب بطئاً غير مبرر في استجابة واجهة المستخدم. الاحتفاظ بهذه البيانات محلياً هو الحل الهندسي الصحيح.
| 1 | <!-- architecture-demo.component.html --> |
| 2 | <div class="architecture-wrapper"> |
| 3 | <h3>لوحة اختبار هندسة البيانات</h3> |
| 4 | <p class="desc">اختر النمط المناسب حسب طبيعة البيانات لضمان استدامة النظام المعماري.</p> |
| 5 | |
| 6 | <div class="demo-grid"> |
| 7 | <div class="section-card"> |
| 8 | <h4>العنصر الأول: حالة محلية</h4> |
| 9 | <app-local-counter></app-local-counter> |
| 10 | </div> |
| 11 | |
| 12 | <div class="section-card"> |
| 13 | <h4>العنصر الثاني: حالة عامة مشتركة</h4> |
| 14 | <p>حالة المستخدم المسجل يتم جلبها من المتجر المركزي العام.</p> |
| 15 | </div> |
| 16 | </div> |
| 17 | </div> |
| 1 | /* architecture-demo.component.css */ |
| 2 | .architecture-wrapper { |
| 3 | background: #0f172a; |
| 4 | color: #f8fafc; |
| 5 | padding: 24px; |
| 6 | border-radius: 12px; |
| 7 | border: 1px solid #1e293b; |
| 8 | } |
| 9 | |
| 10 | .desc { |
| 11 | color: #94a3b8; |
| 12 | margin-bottom: 20px; |
| 13 | } |
| 14 | |
| 15 | .demo-grid { |
| 16 | display: grid; |
| 17 | grid-template-columns: 1fr 1fr; |
| 18 | gap: 16px; |
| 19 | } |
| 20 | |
| 21 | .section-card { |
| 22 | background: #1e293b; |
| 23 | padding: 16px; |
| 24 | border-radius: 8px; |
| 25 | border: 1px solid #334155; |
| 26 | } |
| 27 | |
| 28 | .section-card h4 { |
| 29 | color: #38bdf8; |
| 30 | margin-top: 0; |
| 31 | } |