Ona iki çözüm var!
1. ChangeDetectionStrategy'i OnPush olarak değiştirin
Bu çözüm için temel olarak açısal olarak şunu söylersiniz:
Değişiklikleri kontrol etmeyi bırakın; bunu sadece gerekli olduğunu bildiğimde yapacağım
Hızlı düzeltme:
Bileşeninizi kullanacak şekilde değiştirin ChangeDetectionStrategy.OnPush
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent implements OnInit {
// ...
}
Bununla birlikte, işler artık işe yaramıyor gibi görünüyor. Çünkü bundan böyle detectChanges()
manuel olarak Açısal çağrı yapmanız gerekecek .
this.cdr.detectChanges();
İşte ChangeDetectionStrategy'yi anlamama yardımcı olan bir bağlantı :
https://alligator.io/angular/change-detection-strategy/
2. İfadeyi AnlamaDeğiştirilmişAfterItHasBeenCheckedError
İşte bu hatanın nedenleri hakkında tomonari_t cevabından küçük bir alıntı, sadece bunu anlamama yardımcı olan parçaları dahil etmeye çalıştım.
Makalenin tamamı burada gösterilen her noktaya ilişkin gerçek kod örneklerini göstermektedir.
Temel neden açısal yaşam döngüsünün:
Her işlemden sonra Angular bir işlemi gerçekleştirmek için hangi değerleri kullandığını hatırlar. Bileşenler görünümünün oldValues özelliğinde saklanırlar.
Tüm bileşenler için kontroller yapıldıktan sonra Angular bir sonraki sindirim döngüsünü başlatır, ancak işlemleri gerçekleştirmek yerine mevcut değerleri bir önceki sindirim çevriminden hatırladığı değerlerle karşılaştırır.
Aşağıdaki işlemler özet döngüsünde kontrol ediliyor:
alt bileşenlere aktarılan değerlerin, bu bileşenlerin özelliklerini güncellemek için kullanılacak değerlerle aynı olduğunu kontrol edin.
DOM öğelerini güncellemek için kullanılan değerlerin, bu öğeleri güncellemek için kullanılacak değerlerle aynı olduğunu kontrol edin.
tüm alt bileşenler için kontroller
Ve böylece, karşılaştırılan değerler farklı olduğunda hata atılır. , blog yazarı Max Koretskyi şunları söyledi:
Suçlu daima alt öğedir veya bir direktiftir.
Ve son olarak, genellikle bu hataya neden olan bazı gerçek dünya örnekleri:
- Paylaşılan hizmetler
- Senkron olay yayını
- Dinamik bileşen örneği
Her örnek burada bulunabilir (plunkr), benim durumumda sorun dinamik bir bileşen örneğiydi.
Ayrıca, kendi deneyimlerime göre, herkesin setTimeout
çözümü önlemek için şiddetle tavsiye ediyorum , benim durumumda "neredeyse" sonsuz bir döngüye neden oldu (bunları nasıl kışkırtmayı göstermeye istekli olmadığımı 21 çağrı),
Her zaman akılda tutmanızı tavsiye ederim Açısal yaşam döngüsü, böylece başka bir bileşenin değerini her değiştirdiğinizde nasıl etkileneceğini dikkate alabilirsiniz. Bu hata ile Angular size şunları söylüyor:
Belki de bunu yanlış yapıyorsun, haklı olduğuna emin misin?
Aynı blog şunları da söylüyor:
Genellikle düzeltme, dinamik bir bileşen oluşturmak için doğru değişiklik algılama kancasını kullanmaktır
Benim için kısa bir rehber kodlama sırasında en azından aşağıdaki iki şeyi düşünmektir ( zamanla tamamlamaya çalışacağım ):
- Üst bileşen değerlerini alt öğelerinin bileşenlerinde değiştirmekten kaçının, bunun yerine: üst öğeden değiştirin.
- Kullandığınızda
@Input
ve @Output
yönergeler, bileşen tamamen başlatılmadıkça lyfecycle değişikliklerini tetiklemekten kaçının.
- Gereksiz çağrılardan kaçının
this.cdr.detectChanges();
, özellikle çok fazla dinamik veriyle uğraşırken daha fazla hatayı tetikleyebilirler
- Kullanımı
this.cdr.detectChanges();
zorunlu olduğunda, kullanılan değişkenlerin ( @Input, @Output, etc
) sağ algılama kancasında ( OnInit, OnChanges, AfterView, etc
) doldurulduğundan / başlatıldığından emin olun.
- Mümkün olduğunda, saklamak yerine kaldırın , bu 3. ve 4. nokta ile ilgilidir.
Ayrıca
Angular Life Hook'u tam olarak anlamak istiyorsanız, burada resmi belgeleri okumanızı tavsiye ederim: