| اسم الطريقة (Method) | التأثير الهندسي على المكون | متى يتم استخدامها برمجياً |
|---|---|---|
| cdr.detach() | فصل المكون كلياً عن شجرة اكتشاف التغييرات التلقائية | عند الرغبة في تجميد التحديثات تماماً لمنع أي فحص غير ضروري |
| cdr.detectChanges() | تنفيذ دورة فحص وتحديث يدوية لمرة واحدة فقط | عندما تتغير البيانات في الخلفية وتريد تحديث الواجهة فوراً دون انتظار الأحداث |
| cdr.reattach() | إعادة ربط المكون بشجرة الفحص التلقائي مرة أخرى | عند انتهاء العمليات المكثفة والعودة للعمل بالطريقة العادية |
| cdr.markForCheck() | إعلام نظام OnPush بإجراء تحديث في دورة الفحص القادمة | عند الرغبة في جدولة تحديث لمكون يعمل باستراتيجية OnPush |
نستكمل في هذا الدرس الرابع من الفصل السادس رحلة التحكم المتقدم بالأداء من خلال التعرف على كيفية إيقاف واستئناف آلية اكتشاف التغييرات يدوياً (Manual Change Detection Control) باستخدام الخدمة القوية ChangeDetectorRef في إصدار Angular 22.1. في بعض السيناريوهات الخاصة، مثل التعامل مع تدفقات بيانات ضخمة جداً أو مكتبات خارجية غير متزامنة تحدث تكرارات مستمرة، قد تحتاج إلى فصل المكون كلياً عن نظام الفحص التلقائي وتولي زمام الأمور برمجياً لرفع كفاءة الأداء إلى اقصى حد ممكن.
عندما تستدعي this.cdr.detach() داخل المكون، فإن أنجولر يتجاهل هذا المكون وأبناءه تماماً أثناء دورات اكتشاف التغييرات، حتى وإن حدثت تفاعلات أو تغيرت متغيرات بداخله. هذا يمنع إعادة الرسم غير الضروري، مما يوفر طاقة المعالج بشكل هائل في الواجهات المعقدة.
عندما يكون المكون مفصولاً، يمكنك استخدام this.cdr.detectChanges() لإجبار محرك أنجولر على فحص المكون وتحديث الواجهة يدوياً في اللحظة التي تريدها فقط، مما يمنحك تحكماً كاملاً ودقيقاً في دورة حياة بيانات التطبيق.
| 1 | import { Component, ChangeDetectorRef, inject, OnDestroy } from '@angular/core'; |
| 2 | |
| 3 | @Component({ |
| 4 | selector: 'app-manual-detection-demo', |
| 5 | standalone: true, |
| 6 | template: ` |
| 7 | <div class="manual-box"> |
| 8 | <h3>التحكم اليدوي باكتشاف التغييرات</h3> |
| 9 | <p>العداد المتزايد في الخلفية: <strong>{{ backgroundCounter }}</strong></p> |
| 10 | |
| 11 | <button (click)="triggerManualCheck()">تحديث الواجهة يدوياً (detectChanges)</button> |
| 12 | <button (click)="toggleDetachState()">{{ isDetached ? 'إعادة الربط' : 'فصل الكشف' }}</button> |
| 13 | </div> |
| 14 | ` |
| 15 | }) |
| 16 | export class ManualDetectionDemoComponent implements OnDestroy { |
| 17 | backgroundCounter = 0; |
| 18 | isDetached = false; |
| 19 | private timerId: any; |
| 20 | |
| 21 | // حقن مرجع كاشف التغييرات |
| 22 | private cdr = inject(ChangeDetectorRef); |
| 23 | |
| 24 | constructor() { |
| 25 | // فصل المكون افتراضياً عند الإنشناء للاختبار |
| 26 | this.cdr.detach(); |
| 27 | this.isDetached = true; |
| 28 | |
| 29 | // زيادة العداد في الخلفية كل ثانية دون أن تتحدث الواجهة تلقائياً |
| 30 | this.timerId = setInterval(() => { |
| 31 | this.backgroundCounter++; |
| 32 | console.log('تغيرت القيمة في الخلفية إلى:', this.backgroundCounter); |
| 33 | }, 1000); |
| 34 | } |
| 35 | |
| 36 | triggerManualCheck() { |
| 37 | // إجبار أنجولر على فحص وتحديث الواجهة بالقيم الحالية يدوياً |
| 38 | this.cdr.detectChanges(); |
| 39 | } |
| 40 | |
| 41 | toggleDetachState() { |
| 42 | if (this.isDetached) { |
| 43 | this.cdr.reattach(); |
| 44 | this.isDetached = false; |
| 45 | console.تم(' إعادة ربط المكون بشجرة الكشف التلقائي.'); |
| 46 | } else { |
| 47 | this.cdr.detach(); |
| 48 | this.isDetached = true; |
| 49 | console.log(' تم فصل المكون عن شجرة الكشف.'); |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | ngOnDestroy() { |
| 54 | clearInterval(this.timerId); |
| 55 | } |
| 56 | } |
| 1 | import { Component, ChangeDetectionStrategy, ChangeDetectorRef, inject, signal } from '@angular/core'; |
| 2 | |
| 3 | @Component({ |
| 4 | selector: 'app-mark-for-check-demo', |
| 5 | standalone: true, |
| 6 | changeDetection: ChangeDetectionStrategy.OnPush, |
| 7 | template: ` |
| 8 | <div class="box-mark"> |
| 9 | <h4>مكون يعتمد على الجدولة اليدوية</h4> |
| 10 | <p>الوقت الحالي المسجل: <strong>{{ currentTime }}</strong></p> |
| 11 | |
| 12 | <button (click)="updateTimeManually()">تحديث الوقت وجدولة الفحص</button> |
| 13 | </div> |
| 14 | ` |
| 15 | }) |
| 16 | export class MarkForCheckDemoComponent { |
| 17 | currentTime = new Date().toLocaleTimeString(); |
| 18 | private cdr = inject(ChangeDetectorRef); |
| 19 | |
| 20 | updateTimeManually() { |
| 21 | this.currentTime = new Date().toLocaleTimeString(); |
| 22 | |
| 23 | // إعلام محرك OnPush بضرورة فحص هذا المكون في دورة التحديث القادمة |
| 24 | this.cdr.markForCheck(); |
| 25 | } |
| 26 | } |