AngularJS'de veri bağlama nasıl çalışır?

AngularJS` çerçevesinde veri bağlama nasıl çalışır?

Sitelerinde]1 teknik ayrıntıları bulamadım. Veriler görünümden modele yayıldığında nasıl çalıştığı az çok açık. Ancak AngularJS, setter ve getter'lar olmadan model özelliklerinin değişikliklerini nasıl takip ediyor?

Bu işi yapabilecek JavaScript izleyicileri olduğunu buldum. Ancak Internet Explorer 6 ve Internet Explorer 7'de desteklenmiyorlar. Peki AngularJS, örneğin aşağıdakileri değiştirdiğimi ve bu değişikliği bir görünüme yansıttığımı nasıl biliyor?

myobject.myproperty="new value";
Çözüm

AngularJS değeri hatırlar ve önceki bir değerle karşılaştırır. Bu temel kirli kontroldür. Değerde bir değişiklik varsa, değişiklik olayını ateşler.

AngularJS olmayan bir dünyadan AngularJS dünyasına geçiş yaparken çağırdığınız $apply() yöntemi, $digest() yöntemini çağırır. Özet, sadece eski bir kirli kontroldür. Tüm tarayıcılarda çalışır ve tamamen öngörülebilirdir.

Kirli kontrol (AngularJS) ile değişiklik dinleyicilerini (KnockoutJS ve Backbone.js) karşılaştırmak için: Kirli kontrol basit ve hatta verimsiz görünse de (buna daha sonra değineceğim), anlamsal olarak her zaman doğru olduğu ortaya çıkarken, değişiklik dinleyicilerinin çok sayıda garip köşe durumu vardır ve anlamsal olarak daha doğru hale getirmek için bağımlılık izleme gibi şeylere ihtiyaç duyar. KnockoutJS bağımlılık takibi, AngularJS'nin sahip olmadığı bir sorun için akıllıca bir özelliktir.

Değişiklik dinleyicileriyle ilgili sorunlar:

  • Tarayıcılar yerel olarak desteklemediği için sözdizimi berbattır. Evet, proxy'ler var, ancak her durumda anlamsal olarak doğru değiller ve elbette eski tarayıcılarda proxy yok. Sonuç olarak, dirty-checking POJO yapmanıza izin verirken, KnockoutJS ve Backbone.js sizi kendi sınıflarından miras almaya ve verilerinize accessor'lar aracılığıyla erişmeye zorlar.
  • Birleştirmeyi değiştirin. Bir dizi öğeniz olduğunu varsayalım. Bir diziye öğe eklemek istediğinizi varsayalım, eklemek için döngü oluştururken, her eklediğinizde, kullanıcı arayüzünü oluşturan değişiklik olaylarını ateşliyorsunuz. Bu performans açısından çok kötüdür. İstediğiniz şey, kullanıcı arayüzünü yalnızca bir kez, en sonunda güncellemektir. Değişiklik olayları çok ince tanelidir.
  • Değişim dinleyicileri bir setter üzerinde hemen ateşlenir, bu da bir sorundur, çünkü değişim dinleyicisi verileri daha fazla değiştirebilir ve bu da daha fazla değişim olayı ateşler. Bu kötü bir durumdur çünkü yığınınızda aynı anda birkaç değişiklik olayı gerçekleşiyor olabilir. Herhangi bir nedenle senkronize tutulması gereken iki diziniz olduğunu varsayalım. Yalnızca birine ya da diğerine ekleme yapabilirsiniz, ancak her ekleme yaptığınızda bir değişiklik olayı ateşlersiniz, bu da artık dünyanın tutarsız bir görünümüne sahiptir. Bu, JavaScript'in kaçındığı iş parçacığı kilitlemesine çok benzer bir sorundur, çünkü her geri arama özel olarak ve tamamlanmak üzere yürütülür. Değişim olayları bunu bozar, çünkü ayarlayıcılar amaçlanmayan ve açık olmayan geniş kapsamlı sonuçlara sahip olabilir, bu da iş parçacığı sorununu baştan yaratır. Yapmak istediğiniz şeyin dinleyicinin yürütülmesini geciktirmek ve aynı anda yalnızca bir dinleyicinin çalışmasını garanti etmek olduğu ortaya çıktı, bu nedenle herhangi bir kod verileri değiştirmekte özgürdür ve bunu yaparken başka hiçbir kodun çalışmadığını bilir.

Peki ya performans?

Bu nedenle, kirli kontrol verimsiz olduğu için yavaşmışız gibi görünebilir. Burada sadece teorik argümanlar yerine gerçek sayılara bakmamız gerekiyor, ancak önce bazı kısıtlamaları tanımlayalım.

İnsanlar:

  • Yavaş - 50 ms'den daha hızlı olan her şey insanlar tarafından algılanamaz ve bu nedenle "anlık" olarak kabul edilebilir.

  • Sınırlı - Tek bir sayfada bir insana yaklaşık 2000 parçadan fazla bilgi gösteremezsiniz. Bundan daha fazlası gerçekten kötü bir kullanıcı arayüzüdür ve insanlar bunu zaten işleyemez.

Yani asıl soru şu: Bir tarayıcıda 50 ms içinde kaç karşılaştırma yapabilirsiniz? Birçok faktör devreye girdiği için bu cevaplaması zor bir sorudur, ancak işte bir test örneği: 10.000 izleyici oluşturan http://jsperf.com/angularjs-digest/6. Modern bir tarayıcıda bu işlem 6 ms'nin biraz altında sürer. Internet Explorer 8]4 üzerinde yaklaşık 40 ms sürer. Gördüğünüz gibi, bugünlerde yavaş tarayıcılarda bile bu bir sorun değil. Bir uyarı var: Karşılaştırmaların zaman sınırına sığması için basit olması gerekiyor... Ne yazık ki AngularJS'ye yavaş bir karşılaştırma eklemek çok kolaydır, bu nedenle ne yaptığınızı bilmediğinizde yavaş uygulamalar oluşturmak kolaydır. Ancak, yavaş karşılaştırmaların hangileri olduğunu size gösterecek bir enstrümantasyon modülü sağlayarak bir cevabımız olmasını umuyoruz.

Video oyunları ve GPU'ların özellikle tutarlı olduğu için kirli kontrol yaklaşımını kullandığı ortaya çıktı. Monitör yenileme hızını (genellikle 50-60 Hz veya her 16,6-20 ms'de bir) aştıkları sürece, bunun üzerindeki herhangi bir performans israftır, bu nedenle FPS'yi yükseltmek yerine daha fazla şey çizmeniz daha iyidir.

Yorumlar (38)

Benim temel anlayışım bu. Yanlış da olabilir!

  1. Öğeler bir fonksiyon geçirilerek izlenir (döndürülecek şey izlenen) $watch yöntemine aktarır.
  2. İzlenen öğelerdeki değişiklikler bir kod bloğu içinde yapılmalıdır $apply yöntemi tarafından sarılır.
  3. $applymetodunun sonunda$digestmetodu çağrılır ve şöyle devam eder saatlerin her birini gözden geçirir ve o zamandan beri değişip değişmediğini kontrol eder. son kez$digest` çalıştırıldığında.
  4. Herhangi bir değişiklik bulunursa, tüm değişiklikler dengelenene kadar özet tekrar çağrılır.

Normal geliştirmede, HTML'deki veri bağlama sözdizimi AngularJS derleyicisine sizin için saatleri oluşturmasını söyler ve denetleyici yöntemleri zaten $apply içinde çalıştırılır. Yani uygulama geliştiricisi için her şey şeffaftır.

Yorumlar (4)

Bunu bir süre ben de merak ettim. Ayarlayıcılar olmadan AngularJS $scope nesnesindeki değişiklikleri nasıl fark eder? Onları yokluyor mu?

Aslında yaptığı şey şudur: Modeli değiştirdiğiniz herhangi bir "normal" yer zaten AngularJSnin bağırsaklarından çağrılmıştır, bu nedenle kodunuz çalıştıktan sonra sizin için otomatik olarak $apply çağırır. Diyelim ki kontrolcünüzün bir element üzerinde ng-clicke bağlı bir metodu var. AngularJSbu yöntemin çağrılmasını sizin için birbirine bağladığından, uygun yerde bir$applyyapma şansına sahiptir. Aynı şekilde, doğrudan görünümlerde görünen ifadeler için, bunlarAngularJStarafından yürütülür, böylece$apply` yapar.

Belgeler AngularJSnin dışındaki kodlar için $apply kodunu manuel olarak çağırmak gerektiğinden bahsederken, çalıştırıldığında çağrı yığınında AngularJSnin kendisinden kaynaklanmayan kodlardan bahsediyor.

Yorumlar (0)