Angular’da Değişiklik Algılama Stratejilerini Kullanmak: Detaylı Bir Kılavuz
Giriş: Angular’da Değişiklik Algılama Nedir?
Angular, modern web uygulamaları geliştirmek için güçlü ve popüler bir çerçevedir. Bu çerçevenin temelinde yatan en önemli mekanizmalardan biri, kullanıcı arayüzünü (UI) uygulamanın veri modeliyle senkronize tutan “Değişiklik Algılama” (Change Detection) sistemidir. Bir Angular uygulamasında, verilerde yapılan herhangi bir değişiklik (örneğin, bir API çağrısından gelen yeni veriler, bir kullanıcının form alanına giriş yapması veya bir zamanlayıcının tetiklenmesi) UI’ın güncellenmesini gerektirir. Değişiklik Algılama, bu güncellemelerin ne zaman ve nasıl yapılacağını belirleyen bir süreçtir.
Angular’ın değişiklik algılama mekanizması, uygulamanızın performansını doğrudan etkileyen kritik bir bileşendir. Yanlış yapılandırıldığında veya anlaşılmadığında, gereksiz UI güncellemelerine yol açarak uygulamanızın yavaşlamasına neden olabilir. Ancak doğru kullanıldığında, uygulamanızın hızlı, duyarlı ve verimli çalışmasını sağlar. Bu makalede, Angular’ın değişiklik algılama sisteminin derinliklerine inecek, nasıl çalıştığını, farklı stratejilerini ve bu stratejileri uygulamanızda nasıl etkin bir şekilde kullanabileceğinizi detaylı bir şekilde inceleyeceğiz.
Angular’ın Değişiklik Algılama Mekanizması Nasıl Çalışır?
Angular’ın değişiklik algılama sistemi, temelde iki ana bileşen üzerine kuruludur: Zone.js ve bileşen ağacı. Bu iki bileşen, uygulamanızdaki veri değişikliklerini tespit etmek ve UI’ı buna göre güncellemek için birlikte çalışır.
Zone.js ve Asenkron İşlemler
Angular’ın değişiklik algılama sisteminin kalbinde Zone.js adlı bir kütüphane bulunur. Zone.js, tarayıcının asenkron API’lerini (örneğin, setTimeout, setInterval, XMLHttpRequest, event listener’lar, Promise’ler) “yamalar” (patches). Bu yama işlemi sayesinde, bir asenkron işlemin ne zaman başladığını ve ne zaman bittiğini takip edebilir.
Bir asenkron işlem tamamlandığında (örneğin, bir HTTP isteği başarıyla sonuçlandığında veya bir butona tıklandığında), Zone.js Angular’ı bilgilendirir. Angular, bu bildirimi bir “olası değişiklik” sinyali olarak algılar ve uygulamanın değişiklik algılama döngüsünü tetikler. Bu sayede, geliştiricilerin her veri değişikliğinde manuel olarak UI güncellemesi yapmasına gerek kalmaz; Angular bunu otomatik olarak halleder.
Bazen, Angular’ın değişiklik algılama döngüsünü tetiklememesini istediğimiz durumlar olabilir. Özellikle yüksek frekanslı veya UI ile doğrudan ilgili olmayan asenkron işlemler için bu durum geçerlidir. Bu senaryolarda, NgZone servisini kullanarak belirli kod bloklarını Angular’ın Zone’u dışında çalıştırabiliriz. NgZone.runOutsideAngular() metodu, bu tür işlemleri Angular’ın değişiklik algılama mekanizmasını tetiklemeden gerçekleştirmek için kullanılır.
Değişiklik Algılama Ağacı (Change Detection Tree)
Bir Angular uygulaması, bileşenlerden oluşan bir ağaç yapısına sahiptir. En üstte genellikle AppComponent bulunur ve diğer tüm bileşenler bu ana bileşenin altındaki dallar olarak konumlanır. Angular’ın değişiklik algılama süreci, bu bileşen ağacı üzerinde yukarıdan aşağıya doğru ilerler.
Bir değişiklik algılama döngüsü tetiklendiğinde, Angular ağacın en üstündeki bileşenden başlayarak her bir bileşenin şablonunda kullanılan verilerin değişip değişmediğini kontrol eder. Bu kontrol işlemi, bileşenlerin @Input() özellikleri, şablon ifadeleri ve bileşenin içindeki herhangi bir veri bağlama için yapılır. Eğer bir bileşenin verileri değişmişse, Angular o bileşenin şablonunu yeniden render eder ve ardından alt bileşenlerine geçer. Bu tek yönlü veri akışı, değişikliklerin öngörülebilir bir şekilde yayılmasını sağlar ve döngüsel bağımlılıkları önler.
Değişiklik Algılama Döngüsü
Bir değişiklik algılama döngüsü, aşağıdaki olaylardan herhangi biri tarafından tetiklenebilir:
* Asenkron Tarayıcı Olayları: setTimeout(), setInterval(), Promise.then(), XMLHttpRequest (HTTP istekleri), DOM olayları (click, keyup vb.).
* Veri Değişiklikleri: @Input() özellikleri aracılığıyla bir üst bileşenden alt bileşene gelen verilerin değişmesi.
* Manuel Tetiklemeler: ChangeDetectorRef servisi aracılığıyla yapılan manuel tetiklemeler (ileride detaylandırılacaktır).
Bir döngü tetiklendiğinde, Angular tüm bileşen ağacını yukarıdan aşağıya doğru kontrol eder. Bu kontrol sırasında, Angular her bileşenin mevcut durumunu bir önceki durumuyla karşılaştırır. Eğer bir fark bulunursa, bileşenin görünümü güncellenir. Bu işlem, uygulamanın veri modelinin UI ile her zaman senkronize kalmasını sağlar.
Değişiklik Algılama Stratejileri: Default vs. OnPush
Angular, bileşenlerinizin değişiklikleri nasıl algılayacağını kontrol etmek için iki ana strateji sunar: Default ve OnPush. Bu stratejiler, bileşen bazında belirlenebilir ve uygulamanızın performansını önemli ölçüde etkileyebilir.
Default Strateji (ChangeDetectionStrategy.Default)
Bu, Angular bileşenleri için varsayılan değişiklik algılama stratejisidir. Bir bileşen için açıkça bir strateji belirtmediğinizde, Angular otomatik olarak Default stratejisini kullanır.
* Nasıl Çalışır? Default stratejisi, uygulamanın Zone’u içinde herhangi bir asenkron olay (HTTP isteği, DOM olayı, zamanlayıcı vb.) meydana geldiğinde veya bir @Input() değeri değiştiğinde, Angular’ın tüm bileşen ağacını yukarıdan aşağıya doğru kontrol etmesini sağlar. Bu, her değişiklik algılama döngüsünde, kök bileşenden başlayarak tüm alt bileşenlerin (stratejileri ne olursa olsun) verilerinin değişip değişmediğini kontrol edildiği anlamına gelir.
* Avantajları:
* Basitlik: Geliştiricinin değişiklik algılama hakkında fazla düşünmesine gerek kalmaz. Herhangi bir veri değişikliği olduğunda UI’ın güncelleneceği garanti edilir.
* Güvenilirlik: Mutasyona uğramış (değiştirilebilir) verilerle çalışırken bile her zaman doğru sonuç verir.
* Dezavantajları:
* Performans Yükü: Özellikle büyük ve karmaşık uygulamalarda, her döngüde tüm bileşen ağacını kontrol etmek gereksiz yere zaman alabilir. Bu, uygulamanın yavaşlamasına ve kullanıcı deneyiminin düşmesine neden olabilir. Bir bileşenin verileri değişmese bile, Angular onu kontrol edecektir.
* Ne Zaman Kullanılır? Küçük uygulamalar veya hızlı prototipler için yeterli olabilir. Ancak performans kritik uygulamalarda genellikle OnPush stratejisi tercih edilir.
OnPush Stratejisi (ChangeDetectionStrategy.OnPush)
OnPush stratejisi, Angular’ın değişiklik algılama mekanizması üzerinde daha fazla kontrol sağlayarak performansı artırmak için tasarlanmıştır. Bu strateji, bileşenin ve alt bileşenlerinin yalnızca belirli koşullar altında kontrol edilmesini sağlar.
Bir bileşen OnPush stratejisi ile yapılandırıldığında, Angular o bileşeni (ve dolayısıyla alt bileşenlerini) yalnızca aşağıdaki durumlarda kontrol eder:
1. Giriş Referansları Değiştiğinde: Bileşenin @Input() özellikleri aracılığıyla gelen verilerin referansı değiştiğinde. Bu, özellikle immutable (değişmez) veri yapıları kullanıldığında çok etkilidir. Eğer bir nesnenin veya dizinin içeriği değişir ancak referansı aynı kalırsa, OnPush bileşeni otomatik olarak kontrol etmez.
2. Bileşenin Kendisinden veya Alt Bileşenlerinden Bir Olay Tetiklendiğinde: Bileşenin kendi şablonunda veya alt bileşenlerinin şablonunda bir DOM olayı (örneğin, bir buton tıklaması, form girişi) meydana geldiğinde.
3. async Pipe Kullanıldığında: Bileşenin şablonunda bir Observable veya Promise ile async pipe kullanıldığında ve bu Observable yeni bir değer yaydığında. async pipe, Angular’a otomatik olarak bileşeni kontrol etmesi gerektiğini bildirir.
4. Manuel Olarak Tetiklendiğinde: ChangeDetectorRef servisi kullanılarak markForCheck() veya detectChanges() metotları çağrıldığında.
* Avantajları:
* Önemli Performans Kazancı: Gereksiz değişiklik algılama döngülerini ve kontrollerini ortadan kaldırır. Yalnızca gerçekten değişmesi gereken bileşenler kontrol edilir.
* Daha Öngörülebilir Davranış: Bileşenlerin ne zaman güncelleneceği daha net hale gelir.
* Immutable Veri Kullanımını Teşvik Eder: Performans avantajlarından tam olarak yararlanmak için immutable veri yapıları kullanmaya teşvik eder, bu da uygulamanın daha kararlı ve hatasız olmasına yardımcı olur.
* Dezavantajları:
* Daha Fazla Dikkat Gerektirir: Mutasyona uğramış verilerle çalışırken dikkatli olunmalıdır. Eğer bir nesnenin içini değiştirir ama referansını değiştirmezseniz, OnPush bileşeniniz güncellenmeyebilir.
* Öğrenme Eğrisi: Özellikle yeni başlayanlar için OnPush stratejisi ve ChangeDetectorRef kullanımı başlangıçta biraz karmaşık gelebilir.
* Ne Zaman Kullanılır? Büyük ve karmaşık uygulamalarda, performansın kritik olduğu durumlarda ve mümkünse her bileşende OnPush stratejisinin kullanılması şiddetle tavsiye edilir. Genellikle, bileşenlerin çoğu stateless (durumsuz) veya dumb (aptal) bileşenler olduğundan, OnPush onlar için mükemmel bir seçimdir.
OnPush Stratejisi ile Çalışmak: Detaylar ve En İyi Uygulamalar
OnPush stratejisi, Angular uygulamalarınızın performansını optimize etmek için güçlü bir araçtır. Ancak, doğru bir şekilde kullanılmadığında beklenmedik davranışlara yol açabilir. İşte OnPush ile çalışırken dikkat etmeniz gereken detaylar ve en iyi uygulamalar:
Immutable Veri Yapıları
OnPush stratejisinin en temel gereksinimlerinden biri, @Input() özellikleri aracılığıyla bileşenlere iletilen verilerin immutable (değişmez) olmasıdır. Angular, OnPush bileşenini yalnızca @Input() referansı değiştiğinde kontrol eder.
* Mutable (Değişebilir) Veri Örneği:
// Parent Component
data = { value: 'initial' };
changeData() {
this.data.value = 'updated'; // Referans değişmiyor, sadece içerik
}
// Child Component (OnPush)
@Input() data: { value: string };
Yukarıdaki senaryoda, changeData() çağrıldığında data nesnesinin referansı değişmediği için ChildComponent otomatik olarak güncellenmeyecektir.
* Immutable (Değişmez) Veri Örneği:
// Parent Component
data = { value: 'initial' };
changeDataImmutable() {
this.data = { ...this.data, value: 'updated' }; // Yeni bir referans oluşturuluyor
}
// Veya bir dizi için:
items = [1, 2, 3];
addItemImmutable() {
this.items = [...this.items, 4]; // Yeni bir dizi referansı oluşturuluyor
}
// Child Component (OnPush)
@Input() data: { value: string };
@Input() items: number[];
Bu örneklerde, data veya items nesnelerinin yeni bir referansı oluşturulduğu için ChildComponent doğru bir şekilde güncellenecektir. Immutable.js veya Immer gibi kütüphaneler, daha karmaşık immutable veri yönetimi için kullanılabilir.
Async Pipe (async pipe)
async pipe, OnPush stratejisi ile birlikte kullanıldığında mükemmel bir uyum sağlar. Bir Observable veya Promise ile kullanıldığında, async pipe otomatik olarak şunları yapar:
* Observable yeni bir değer yaydığında, Angular’a bu bileşeni markForCheck() ile işaretlemesini ve bir sonraki değişiklik algılama döngüsünde kontrol etmesini bildirir.
* Bileşen yok edildiğinde (destroyed), Observable aboneliğini otomatik olarak kaldırır, böylece bellek sızıntılarını önler.
Bu, OnPush bileşenlerinde Observable‘ları yönetmenin en temiz ve performanslı yoludur.
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Observable, interval } from 'rxjs';
import { map } from 'rxjs/operators';
@Component({
selector: 'app-async-data',
template:
Async Pipe ile Veri:
Sayı: {{ counter$ | async }}
,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AsyncDataComponent {
counter$: Observable;
constructor() {
this.counter$ = interval(1000).pipe(map(val => val + 1));
}
}
Yukarıdaki örnekte, interval Observable her saniye yeni bir değer yaydığında, async pipe AsyncDataComponent‘i otomatik olarak kontrol ettirir ve UI güncellenir.
ChangeDetectorRef Sınıfı
ChangeDetectorRef sınıfı, OnPush stratejisi ile çalışırken değişiklik algılama sürecini manuel olarak kontrol etmenizi sağlayan güçlü bir araçtır.
* markForCheck(): Bu metod, bileşenin (veya üst bileşenlerinin) durumunun değişmiş olabileceğini Angular’a bildirir ve bir sonraki değişiklik algılama döngüsünde bileşenin kontrol edilmesini sağlar. markForCheck() metodu, bileşenin @Input() referansı değişmediğinde ancak iç durumu (örneğin, bir servisten gelen verilerle güncellenen özel bir özellik) değiştiğinde kullanışlıdır. Bu metod sadece bileşeni kontrol için işaretler, hemen bir değişiklik algılama döngüsü tetiklemez.
import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'app-manual-check',
template:
Manual Check ile Veri:
Mesaj: {{ message }}
,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ManualCheckComponent {
message: string = 'İlk Mesaj';
constructor(private cdr: ChangeDetectorRef) {}
updateMessage() {
this.message = 'Güncellenmiş Mesaj ' + new Date().toLocaleTimeString();
// Input referansı değişmediği için manuel olarak işaretlememiz gerekiyor
this.cdr.markForCheck();
}
}
* detectChanges(): Bu metod, geçerli bileşenin ve tüm alt bileşenlerinin değişikliklerini hemen algılamaya zorlar. Bu, markForCheck()‘ten farklı olarak, hemen bir değişiklik algılama döngüsü başlatır ve sadece bu bileşen dalını kontrol eder. detectChanges() genellikle dikkatli kullanılmalıdır, çünkü sık veya yanlış kullanımı performansı olumsuz etkileyebilir. Özellikle üçüncü taraf kütüphanelerle veya Angular’ın Zone’u dışında çalışan kodlarla entegrasyon yaparken faydalı olabilir.
* detach() ve reattach(): Bu metodlar, bir bileşeni değişiklik algılama ağacından tamamen ayırmanıza ve gerektiğinde yeniden bağlamanıza olanak tanır. Çok yüksek frekanslı güncellemelerin olduğu (örneğin, bir oyun döngüsü veya bir video akışı) ve UI’ın yalnızca belirli aralıklarla güncellenmesini istediğiniz nadir durumlar için kullanışlıdır. detach() çağrıldığında, bileşen ve alt bileşenleri artık otomatik olarak kontrol edilmez. reattach() çağrıldığında ise tekrar değişiklik algılama ağacına dahil edilirler.
* checkNoChanges(): Bu metod, yalnızca geliştirme modunda kullanılmak üzere tasarlanmıştır. Mevcut değişiklik algılama döngüsünün sonunda, bileşende herhangi bir değişiklik olmadığını doğrulamak için kullanılır. Eğer bu metod çağrıldığında bir değişiklik tespit edilirse, Angular bir hata fırlatır. Bu, “tek yönlü veri akışı” kuralının ihlal edildiği durumları (yani, bir bileşenin şablonunda bir değeri değiştirmesi ve bu değişikliğin aynı döngüde başka bir bileşeni etkilemesi) tespit etmek için yararlıdır.
Eventler ve OnPush
OnPush stratejisine sahip bir bileşende, bileşenin kendi şablonunda veya alt bileşenlerinin şablonunda bir DOM olayı (click, keyup vb.) tetiklendiğinde, Angular otomatik olarak o bileşeni (ve dolayısıyla alt bileşenlerini) kontrol eder. Bu, kullanıcı etkileşimlerinin her zaman UI’ı güncellemesini sağlar ve çoğu durumda markForCheck() çağırmaya gerek kalmaz.
import { Component, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'app-event-driven',
template:
Event Driven OnPush:
Sayaç: {{ count }}
,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class EventDrivenComponent {
count: number = 0;
increment() {
this.count++; // Bu değişiklik, click olayı sayesinde algılanır.
}
}
Pipe’lar ve OnPush
Angular pipe’ları, verileri şablonda dönüştürmek için kullanılır. Pipe’lar varsayılan olarak “pure” (saf) olarak kabul edilir.
* Pure Pipe’lar: Yalnızca giriş değerleri değiştiğinde yeniden yürütülür. Bu, OnPush stratejisi ile mükemmel bir şekilde çalışır, çünkü pipe’ın gereksiz yere çalışmasını engeller.
* Impure Pipe’lar: Her değişiklik algılama döngüsünde yeniden yürütülür. OnPush bileşenlerinde bile impure pipe’lar her zaman çalışır, bu nedenle dikkatli kullanılmalıdır. Genellikle, impure pipe’lardan kaçınmak veya yalnızca çok özel durumlarda kullanmak en iyisidir.
Pratik Senaryolar ve Örnekler
Şimdiye kadar öğrendiklerimizi pekiştirmek için bazı pratik senaryolar ve kod örnekleri üzerinden geçelim.
Basit OnPush Bileşeni ve MarkForCheck Kullanımı
Bu örnek, bir üst bileşenin veri gönderdiği ve bir alt OnPush bileşeninin bu veriyi görüntülediği bir senaryoyu gösterir. Alt bileşenin kendi iç durumunu güncellediğinde markForCheck()‘i nasıl kullanması gerektiğini de göstereceğiz.
// app.component.ts (Parent Component)
import { Component } from '@angular/core';
interface User {
name: string;
age: number;
}
@Component({
selector: 'app-root',
template:
,
})
export class AppComponent {
currentUser: User = { name: 'Alice', age: 30 };
changeUserName() {
// Yeni bir referans oluşturarak name özelliğini güncelliyoruz
this.currentUser = { ...this.currentUser, name: 'Bob ' + new Date().toLocaleTimeString() };
}
changeUserAgeMutable() {
// Referansı değiştirmeden age özelliğini güncelliyoruz
this.currentUser.age++;
// Bu durumda UserDetailComponent (OnPush ise) otomatik güncellenmez!
console.log('Yaş güncellendi (mutable):', this.currentUser.age);
}
}
// user-detail.component.ts (Child Component - OnPush)
import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
interface User {
name: string;
age: number;
}
@Component({
selector: 'app-user-detail',
template:
Kullanıcı Detayı (OnPush)
Ad: {{ user.name }}
Yaş: {{ user.age }}
İç Sayaç: {{ internalCounter }}
,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UserDetailComponent {
@Input() user!: User;
internalCounter: number = 0;
constructor(private cdr: ChangeDetectorRef) {}
ngOnInit() {
console.log('UserDetailComponent initialized');
}
ngOnChanges(changes: any) {
console.log('UserDetailComponent ngOnChanges:', changes);
}
incrementInternalCounter() {
this.internalCounter++;
// İç durum değiştiği için OnPush bileşeninin güncellenmesi için işaretliyoruz.
this.cdr.markForCheck();
console.log('İç sayaç arttırıldı:', this.internalCounter);
}
forceDetectChanges() {
// Bu bileşeni ve alt bileşenlerini hemen kontrol etmeye zorlar.
this.cdr.detectChanges();
console.log('Değişiklikler manuel olarak algılandı.');
}
}
Yukarıdaki örnekte:
* changeUserName() metodunu çağırdığınızda, currentUser nesnesinin referansı değiştiği için UserDetailComponent güncellenir.
changeUserAgeMutable() metodunu çağırdığınızda, currentUser nesnesinin referansı değişmediği için UserDetailComponent otomatik olarak güncellenmez*. UI’da age değeri değişmez görünür. Eğer bu değişikliğin UI’a yansımasını isteseydik, ya currentUser nesnesini immutable yapmalıydık ya da UserDetailComponent içinde this.cdr.markForCheck() çağırmalıydık.
* incrementInternalCounter() metodunu çağırdığınızda, internalCounter değişir. markForCheck() çağrılmadıkça UI güncellenmez. markForCheck() sayesinde, bir sonraki değişiklik algılama döngüsünde bu bileşen kontrol edilir.
* forceDetectChanges() metodu, UserDetailComponent‘i hemen kontrol etmeye zorlar.
Formlar ve OnPush
Angular’ın reaktif formları veya template-driven formları, OnPush stratejisiyle iyi çalışır. Bir form kontrolünün değeri değiştiğinde, ilgili DOM olayı (örneğin input olayı) OnPush bileşenini tetikler ve değişiklikler algılanır. Ancak, bazen özel form kontrolleri veya dışarıdan gelen verilerle formun değerini manuel olarak ayarladığınızda, markForCheck() kullanmanız gerekebilir.
import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'app-form-onpush',
template:
Form ile OnPush
Form Değeri: {{ nameControl.value }}
,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FormOnpushComponent {
nameControl = new FormControl('Varsayılan Ad');
constructor(private cdr: ChangeDetectorRef) {}
setNameProgrammatically() {
this.nameControl.setValue('Yeni Ad ' + new Date().toLocaleTimeString());
// setValue() bir DOM olayı tetiklemediği için, OnPush bileşeninin güncellenmesi için işaretlememiz gerekebilir.
// Ancak FormControl'ün kendisi bir Observable'a sahip olduğu için genellikle bu gerekli değildir.
// Yine de karmaşık senaryolarda akılda bulundurulmalıdır.
this.cdr.markForCheck();
}
}
Değişiklik Algılama Performansını İzleme ve Optimize Etme
Uygulamanız büyüdükçe, değişiklik algılama performansını izlemek ve optimize etmek kritik hale gelir.
* Angular DevTools: Chrome uzantısı olarak sunulan Angular DevTools, uygulamanızdaki bileşen ağacını ve her bir değişiklik algılama döngüsünde hangi bileşenlerin kontrol edildiğini görselleştirmek için harika bir araçtır. Profiler sekmesi, değişiklik algılama sürelerini ve hangi bileşenlerin en çok zaman aldığını gösterir.
* Chrome DevTools (Performance Tab): Genel tarayıcı performansı için Chrome DevTools’un Performance sekmesini kullanabilirsiniz. Burada, Angular’ın değişiklik algılama döngülerinin neden olduğu “Scripting” sürelerini görebilirsiniz.
* Optimizasyon Stratejileri:
* OnPush Stratejisini Kullanın: Mümkün olan her yerde OnPush stratejisini varsayılan olarak kabul edin.
* Immutable Veri Kullanın: @Input() ile gelen verileri değiştirirken her zaman yeni referanslar oluşturun.
* async Pipe’ı Kullanın: Observable‘lar ile çalışırken async pipe’ı tercih edin.
trackBy ile ngFor: *ngFor döngülerinde trackBy fonksiyonunu kullanarak, yalnızca değişen öğelerin yeniden render edilmesini sağlayın.
* NgZone.runOutsideAngular(): Yüksek frekanslı, UI ile doğrudan ilgili olmayan işlemler için bu metodu kullanarak Angular’ın değişiklik algılama döngüsünü tetiklemekten kaçının.
* Gereksiz Bileşenleri Ayırın (detach()): Çok nadir durumlarda, belirli bileşenleri değişiklik algılama ağacından geçici olarak ayırarak performansı artırabilirsiniz.
Sonuç
Angular’ın değişiklik algılama mekanizması, uygulamanızın reaktif ve verimli olmasını sağlayan temel bir özelliktir. Default stratejisi başlangıç için basitlik sunsa da, OnPush stratejisi büyük ve performans kritik uygulamalar için vazgeçilmezdir. OnPush‘i benimsemek, geliştiricileri immutable veri yapılarını kullanmaya teşvik eder ve async pipe ile ChangeDetectorRef gibi araçlarla daha performanslı ve öngörülebilir uygulamalar yazmalarına olanak tanır.
Bu makalede ele alınan kavramları ve en iyi uygulamaları anlayarak ve uygulayarak, Angular uygulamalarınızın performansını önemli ölçüde artırabilir, daha iyi bir kullanıcı deneyimi sunabilir ve daha sürdürülebilir bir kod tabanı oluşturabilirsiniz. Değişiklik algılama, Angular ekosisteminin en güçlü ve en önemli yönlerinden biridir ve her Angular geliştiricisinin derinlemesine anlaması gereken bir konudur.