Açısal Değişim Algılama ve OnPush Stratejisi
Yayınlanan: 2022-03-11Tüm favori projeleriniz için Angular'ı kullanmaya başladınız. Angular'ın neler sunabileceğini ve harika web uygulamaları oluşturmak için bundan nasıl yararlanabileceğinizi biliyorsunuz. Ancak, Angular hakkında bazı şeyler vardır ve bunları bilmek, projeleriniz için Angular'ı daha iyi kullanmanızı sağlayabilir.
Veri akışı hemen hemen her şeyin merkezinde yer alır Angular, değişiklik algılama, hataları çok daha kolay izlemenize yardımcı olacağı ve karmaşık bir veri kümesiyle çalışırken uygulamalarınızı daha da optimize etme fırsatı vereceği için bilmeye değer bir şeydir.
Bu makalede, Angular'ın veri yapılarındaki değişiklikleri nasıl algıladığını ve Angular'ın değişiklik algılama stratejilerinden en iyi şekilde yararlanmak için bunları nasıl değişmez hale getirebileceğinizi öğreneceksiniz.
Angular'da Değişim Algılama
Modellerinizden herhangi birini değiştirdiğinizde, Angular değişiklikleri algılar ve görünümleri anında günceller. Bu, Angular'da değişiklik tespitidir. Bu mekanizmanın amacı, altta yatan görünümlerin her zaman karşılık gelen modellerle senkronize olduğundan emin olmaktır. Angular'ın bu temel özelliği, çerçeveyi harekete geçiren şeydir ve kısmen Angular'ın modern web uygulamaları geliştirmek için mükemmel bir seçim olmasının nedenidir.
Angular'daki bir model, aşağıdaki senaryolardan herhangi birinin sonucu olarak değişebilir:
DOM olayları (tıklayın, üzerine gelin vb.)
AJAX istekleri
Zamanlayıcılar (setTimer(), setInterval())
Dedektörleri Değiştir
Tüm Angular uygulamaları, hiyerarşik bir bileşen ağacından oluşur. Çalışma zamanında, Angular ağaçtaki her bileşen için ayrı bir değişiklik algılayıcı sınıfı oluşturur ve bu daha sonra bileşenlerin hiyerarşi ağacına benzer bir değişiklik algılayıcı hiyerarşisi oluşturur.
Değişiklik algılama tetiklendiğinde, Angular, herhangi birinin değişiklik bildirip bildirmediğini belirlemek için bu değişiklik algılayıcı ağacında yürür.
Değişiklik algılama döngüsü, her algılanan değişiklik için her zaman bir kez gerçekleştirilir ve kök değişiklik algılayıcıdan başlar ve sıralı bir şekilde aşağı doğru gider. Bu sıralı tasarım seçimi güzel çünkü bileşen verilerinin yalnızca üst öğesinden gelebileceğini bildiğimiz için modeli öngörülebilir bir şekilde güncelliyor.
Değişiklik algılayıcıları, değişiklikleri Angular'a bildirmek için bileşenin önceki ve mevcut durumlarının yanı sıra yapısını takip etmenin bir yolunu sağlar.
Angular, raporu bir değişiklik algılayıcıdan alırsa, ilgili bileşene DOM'yi buna göre yeniden oluşturması ve güncellemesi talimatını verir.
Algılama Stratejilerini Değiştirin
Değer ve Referans Türleri
Bir değişiklik algılama stratejisinin ne olduğunu ve neden işe yaradığını anlamak için önce JavaScript'teki değer türleri ve referans türleri arasındaki farkı anlamamız gerekir. Bunun nasıl çalıştığını zaten biliyorsanız, bu bölümü atlayabilirsiniz.
Başlamak için değer türlerini ve referans türlerini ve bunların sınıflandırmalarını gözden geçirelim.
Değer Türleri
Boole
Boş
Tanımsız
Numara
Sicim
Basit olması açısından, bu türlerin değerlerini yığın belleğinde sakladıkları düşünülebilir (ki bu teknik olarak doğru değildir, ancak bu makale için yeterlidir). Örneğin aşağıdaki resimde yığın belleğine ve değerlerine bakın.
Referans Türleri
diziler
nesneler
Fonksiyonlar
Bu türler, yığın belleğinde gerçek değerlerine işaret eden bir referansı yığın belleğinde sakladıklarından biraz daha karmaşıktır. Aşağıdaki örnek resimde yığın bellek ve yığın belleğin birlikte nasıl çalıştığını görebilirsiniz. Yığın belleğinin, yığın belleğindeki referans türünün gerçek değerlerini referans aldığını görüyoruz.
Değer türleri ve referans türleri arasında yapılması gereken önemli ayrım, değer türünün değerini okumak için yığın belleğini sorgulamamız gerektiğidir, ancak bir referans türünün değerini okumak için önce referansı almak için yığın belleğini sorgulayın ve ardından ikinci olarak referans türünün değerini bulmak için yığın belleğini sorgulamak için bu referansı kullanın.
Varsayılan Strateji
Daha önce de belirttiğimiz gibi, Angular, tüm değişiklikleri yakaladığından emin olmak için modeldeki değişiklikleri izler. Genel uygulama modelinin önceki durumu ile mevcut durumu arasındaki farkları kontrol edecektir.
Angular'ın varsayılan değişiklik algılama stratejisinde sorduğu soru şudur: Modelde herhangi bir değer değişti mi? Ancak bir referans türü için, daha iyi bir soru sorabilmemiz için stratejiler uygulayabiliriz. OnPush değişiklik algılama stratejisinin devreye girdiği yer burasıdır.

OnPush Stratejisi
OnPush stratejisinin arkasındaki ana fikir, referans türlerini değişmez nesneler olarak ele alırsak, bir değerin çok daha hızlı değişip değişmediğini tespit edebileceğimizin farkına varılmasından ortaya çıkar. Bir referans türü değişmez olduğunda, bu her güncellendiğinde yığın belleğindeki referansın değişmesi gerektiği anlamına gelir. Şimdi basitçe kontrol edebiliriz: Referans tipinin referansı (yığındaki) değişti mi? Evet ise, ancak o zaman tüm değerleri kontrol edin (yığın üzerinde). Bu kafa karıştırıcıysa, önceki yığın yığın diyagramlarına bakın.
OnPush stratejisi temelde bir yerine iki soru sorar. Referans tipinin referansı değişti mi? Evet ise, yığın bellekteki değerler değişti mi?
Örneğin, 30 elemanlı değişmez bir dizimiz olduğunu ve herhangi bir değişiklik olup olmadığını bilmek istediğimizi varsayalım. Değişmez dizide herhangi bir güncelleme olması için, referansının (yığındaki) değişmiş olması gerektiğini biliyoruz. Bu, başlangıçta diziye yapılan başvurunun farklı olup olmadığını kontrol edebileceğimiz anlamına gelir; bu, potansiyel olarak bizi hangi öğenin farklı olduğunu belirlemek için (yığın içinde) 30 kontrol yapmaktan kurtarabilir. Buna OnPush stratejisi denir.
Öyleyse, referans türlerini değişmez olarak ele almanın ne anlama geldiğini sorabilirsiniz. Bu, bir referans türünün özelliğini hiçbir zaman ayarlamadığımız, bunun yerine değeri hep birlikte yeniden atadığımız anlamına gelir. Aşağıya bakınız:
Nesneleri değişken olarak ele almak:
static mutable() { var before = {foo: "bar"}; var current = before; current.foo = "hello"; console.log(before === current); // => true }
Nesneleri değişmez olarak ele almak:
static mutable() { var before = {foo: "bar"}; var current = before; current = {foo "hello"}; console.log(before === current); // => false }
Yukarıdaki örneklerde, referans türlerini geleneksel olarak değişmez olarak "elde ettiğimizi" unutmayın, bu nedenle sonunda hala değiştirilebilir nesnelerle çalışıyoruz, ancak yalnızca değişmez olduklarını "giyiyoruz".
Peki bir bileşen için OnPush stratejisini nasıl uygularsınız? Tek yapmanız gereken, @Component ek açıklamalarına changeDetection
parametresini eklemek.
import {ChangeDetectionStrategy, Component} from '@angular/core'; @Component({ // ... changeDetection: ChangeDetectionStrategy.OnPush }) export class OnPushComponent { // ... }
Immutable.js
Bir Angular bileşeninde OnPush stratejisini kullanmaya karar verirseniz, değişmezliği zorlamak iyi bir fikirdir. Immutable.js'nin devreye girdiği yer burasıdır.
Immutable.js, Facebook tarafından JavaScript'te değişmezlik için oluşturulmuş bir kitaplıktır. Liste, Harita ve Yığın gibi birçok değişmez veri yapısına sahiptirler. Bu makalenin amaçları için, Liste ve Harita gösterilecektir. Daha fazla referans için lütfen buradaki resmi belgelere bakın.
Projelerinize Immutable.js eklemek için lütfen terminalinize girip şunu çalıştırın:
$ npm install immutable --save
Ayrıca, kullandığınız veri yapılarını, kullandığınız bileşende Immutable.js'den aldığınızdan emin olun.
import {Map, List} from 'immutable';
Immutable.js Haritası şu şekilde kullanılabilir:
var foobar = {foo: "bar"}; var immutableFoobar = Map(foobar); console.log(immutableFooter.get("foo")); // => bar
Ve bir Dizi kullanılabilir:
var helloWorld = ["Hello", "World!"]; var immutableHelloWorld = List(helloWorld); console.log(immutableHelloWorld.first()); // => Hello console.log(immutableHelloWorld.last()); // => World! helloWorld.push("Hello Mars!"); console.log(immutableHelloWorld.last()); // => Hello Mars!
Immutable.js Kullanmanın Dezavantajları
Immutable.js kullanmanın tartışılabilir birkaç ana dezavantajı vardır.
Fark etmiş olabileceğiniz gibi, API'sini kullanmak biraz zahmetlidir ve geleneksel bir JavaScript geliştiricisi bundan hoşlanmayabilir. Daha ciddi bir sorun, Immutable.js arabirimleri desteklemediğinden veri modeliniz için arabirimleri uygulayamamakla ilgilidir.
Sarmak
OnPush stratejisinin neden Angular için varsayılan strateji olmadığını soruyor olabilirsiniz. Bunun, Angular'ın JavaScript geliştiricilerini değişmez nesnelerle çalışmaya zorlamak istemediği için olduğunu tahmin ediyorum. Ancak bu, onu kullanmanızın yasak olduğu anlamına gelmez.
Bu, bir sonraki web projenizde yararlanmak istediğiniz bir şeyse, artık Angular'ın farklı bir değişiklik algılama stratejisine geçmeyi ne kadar kolay hale getirdiğini biliyorsunuz.