| استراتيجية جلب البيانات (`Strategy`) | مكان ووقت جلب البيانات الشبكية | تأثيرها على تجربة المستخدم |
|---|---|---|
| الجلب داخل المكون (`Inside Component`) | يتم إرسال الطلب بعد فتح المكون وعرضه (عبر `ngOnInit`) | قد يظهر للمستخدم هيكل فارغ أو شاشة تحميل مؤقتة أثناء جلب البيانات |
| التحميل المسبق عبر المحللات (`Route Resolvers`) | يتم جلب البيانات بالكامل **قبل** الانتقال الفعلي وعرض المكون | تجربة مستخدم سلسة وفورية، حيث تفتح الصفحة وبداخلها البيانات جاهزة تماماً |
في بعض الأحيان، ترغب في ضمان جلب كافة البيانات الأساسية المطلوبة لعرض الصفحة (مثل ملفات المستخدم أو تفاصيل المنتج) قبل أن يتم رسم المكون على الشاشة، لتجنب ظهور شاشات التحميل الفارغة أو الوميض المزعج. يتيح لك أنجولر إنجاز ذلك باحترافية تامة عبر استخدام المحللات الوظيفية للمسارات (Route Resolvers) التي تجلب البيانات مسبقاً أثناء عملية التنقل.
يعمل المحل كوسيط شبكي ينتظر انتهاء جلب البيانات بنجاح قبل السماح للمسار بالاكتمال وعرض المكون المستهدف.
تُعرف المحللات الحديثة كدوال بسيطة تنفذ نوع ResolveFn، مما يسهل حقن الخدمات واستخدامها مباشرة.
| 1 | import { inject } from '@angular/core'; |
| 2 | import { ResolveFn } from '@angular/router'; |
| 3 | import { HttpClient } from '@angular/common/http'; |
| 4 | import { Observable } from 'rxjs'; |
| 5 | |
| 6 | export interface UserData { |
| 7 | id: number; |
| 8 | name: string; |
| 9 | } |
| 10 | |
| 11 | export const userResolver: ResolveFn<UserData> = (route, state) => { |
| 12 | const http = inject(HttpClient); |
| 13 | const userId = route.paramMap.get('id') || '1'; |
| 14 | |
| 15 | console.log(`[User Resolver] جاري جلب بيانات المستخدم رقم ${userId} مسبقاً قبل عرض المكون...`); |
| 16 | |
| 17 | // جلب البيانات مسبقاً قبل الانتقال الفعلي للمسار |
| 18 | return http.get<UserData>(`https://jsonplaceholder.typicode.com/users/${userId}`); |
| 19 | }; |
| 1 | import { Component, Input, OnInit } from '@angular/core'; |
| 2 | import { CommonModule } from '@angular/common'; |
| 3 | import { UserData } from './user.resolver'; |
| 4 | |
| 5 | @Component({ |
| 6 | selector: 'app-user-profile', |
| 7 | standalone: true, |
| 8 | imports: [CommonModule], |
| 9 | template: ` |
| 10 | <div class="card"> |
| 11 | <h3>ملف المستخدم (تم جلب البيانات مسبقاً)</h3> |
| 12 | <p><strong>اسم المستخدم:</strong> {{ userData.name }}</p> |
| 13 | <p><strong>الرقم التعريفي:</strong> {{ userData.id }}</p> |
| 14 | </div> |
| 15 | `, |
| 16 | styles: [` |
| 17 | .card { background: #090d16; color: #fff; padding: 24px; border-radius: 8px; border: 1px solid #10b981; } |
| 18 | p { color: #38bdf8; } |
| 19 | `] |
| 20 | }) |
| 21 | export class UserProfileComponent implements OnInit { |
| 22 | // استقبال البيانات الجاهزة الممررة عبر خاصية الـ resolve والمربوطة بالمدخلات |
| 23 | @Input() resolvedData!: UserData; |
| 24 | userData!: UserData; |
| 25 | |
| 26 | ngOnInit(): void { |
| 27 | this.userData = this.resolvedData; |
| 28 | console.log('تم تحميل بيانات المكون بنجاح فوري:', this.userData); |
| 29 | } |
| 30 | } |
⚠️ تحذير
تذكر أن حدوث أي خطأ شبكي أو فشل في المحل (مثل تعطل الخادم) سيؤدي إلى إيقاف عملية الانتقال للمسار تماماً! احرص دائماً على معالجة الأخطاء داخل المحل أو إعادة توجيه المستخدم لصفحة بديلة لتجنب توقف واجهة الاستخدام.