React'ın Sanal DOM kavramının neden kirli model kontrolünden daha başarılı olduğu söyleniyor?


372

Bir React dev konuşması gördüm ( Pete Hunt: React: En iyi uygulamaları yeniden düşünmek - JSConf EU 2013 ) ve konuşmacı modelin kirli kontrolünün yavaş olabileceğini belirtti. Ancak sanal DOM'lar arasındaki farkın hesaplanması aslında sanal DOM'un çoğu durumda modelden daha büyük olması gerektiğinden daha az performans göstermiyor mu?

Sanal DOM'un potansiyel gücünü gerçekten seviyorum (özellikle sunucu tarafı oluşturma), ancak tüm artıları ve eksileri bilmek istiyorum.


Bu konuşmadan çok söz edebileceğinizi düşünüyorum. Youtube.com/watch?v=-DX3vJiqxm4 burada özellikle kıstaslardan bahsediyor.
inafalcao

Yanıtlar:


493

Ben bir sanal dom modülünün birincil yazarıyım , bu yüzden sorularınızı cevaplayabilirim. Aslında burada çözülmesi gereken 2 sorun var

  1. Ne zaman yeniden oluştururum? Cevap: Verilerin kirli olduğunu gözlemlediğimde.
  2. Nasıl verimli bir şekilde yeniden oluşturabilirim? Yanıt: Gerçek bir DOM yaması oluşturmak için sanal bir DOM kullanma

React'te bileşenlerinizin her birinin bir durumu vardır. Bu durum nakavtta veya diğer MVVM tarzı kütüphanelerde bulabileceğiniz gözlemlenebilir bir gibidir. Esasen, React sahneyi ne zaman yeniden oluşturacağını bilir , çünkü bu verilerin ne zaman değiştiğini gözlemleyebilir. Kirli kontrol, gözlemlenebilirlerden daha yavaştır, çünkü verileri düzenli aralıklarla yoklamalı ve veri yapısındaki tüm değerleri tekrar tekrar kontrol etmelisiniz. Karşılaştırma yapmak gerekirse, durum üzerinde bir değer ayarlamak, bir durumun değiştiğini bir dinleyiciye sinyal verecektir, böylece React durumdaki değişiklik olaylarını dinleyebilir ve yeniden oluşturma sırasını sıralayabilir.

Sanal DOM, DOM'un verimli bir şekilde yeniden oluşturulması için kullanılır. Bu gerçekten kirli verilerinizi kontrol etmekle ilgili değildir. Kirli denetimle veya denetlemeden sanal bir DOM kullanarak yeniden oluşturabilirsiniz. İki sanal ağaç arasındaki farkın hesaplanmasında bazı ek yükler olduğunu doğru söylüyorsunuz, ancak sanal DOM farkı, verilerinizin değişip değişmediğini DOM'da güncellemenin gerekip gerekmediğini anlamakla ilgilidir. Aslında, diff algoritması kirli bir denetleyicinin kendisidir ancak bunun yerine DOM'un kirli olup olmadığını görmek için kullanılır.

Sanal ağacı yalnızca devlet değiştiğinde yeniden oluşturmayı amaçlıyoruz. Bu nedenle, durumun değişip değişmediğini kontrol etmek için gözlemlenebilir bir yöntem kullanmak, gereksiz yeniden oluşturmaları önlemenin etkili bir yoludur ve bu da çok sayıda gereksiz ağaç farkına neden olur. Hiçbir şey değişmediyse, hiçbir şey yapmayız.

Sanal bir DOM güzel, çünkü kodumuzu tüm sahneyi yeniden oluşturuyormuş gibi yazmamıza izin veriyor. Perde arkasında, DOM'u nasıl beklediğimize bakacak şekilde güncelleyen bir yama işlemi hesaplamak istiyoruz. Dolayısıyla sanal DOM fark / yama algoritması muhtemelen en uygun çözüm olmasa da , uygulamalarımızı ifade etmemiz için bize çok güzel bir yol sunuyor. Sadece tam olarak ne istediğimizi beyan ederiz ve React / virtual-dom, sahnenizi nasıl bu hale getireceğinizi öğrenir. Manuel DOM manipülasyonu yapmamız veya önceki DOM durumu hakkında kafa karıştırmamız gerekmez. Tüm sahneyi yeniden oluşturmak zorunda değiliz, bu da onu düzeltmekten çok daha az verimli olabilir.


1
React bileşen desteklerinde kirli kontrol yapıyor mu? SetProps () işlevi olmadığı için soruyorum.
bennlich


1
böyle bir örnek ne olurdu unnecessary re-renders?
vsync

9
"Sanal DOM fark / yama algoritması muhtemelen en uygun çözüm olmasa da" derseniz, teorik olarak daha uygun bir çözüm var mı?
CMCDragonkai

3
Bu soruya cevap vermiyor gibi görünüyor. React, durumun değiştiğini belirtmek için setState öğesini kullanmanızı gerektirir. Tek yapmanız mümkün olsaydı this.state.cats = 99sizi hala sadece Açısal kirli çekleri $ kapsamı ağaç olarak, model değişikliği için kontrol etmek kirli denetimi gerekir. Bu, iki tekniğin hızının bir karşılaştırması değildir, bunun yerine React'in kirli kontrol yapmadığı, bunun yerine bir Omurga stili ayarlayıcıya sahip olduğu ifadesidir.
superluminary

133

Son zamanlarda React'in diff algoritması hakkında ayrıntılı bir makaleyi burada okudum: http://calendar.perfplanet.com/2013/diff/ . Anladığım kadarıyla React'ı hızlı yapan şey:

  • Toplu DOM okuma / yazma işlemleri.
  • Yalnızca alt ağacın verimli güncellenmesi.

Kirli kontrole kıyasla, IMO'nun temel farkları şunlardır:

  1. Model kirli kontrolü : React bileşeni her setStateçağrıldığında açıkça kirli olarak ayarlanır , bu nedenle burada herhangi bir karşılaştırma (veri) gerekmez. Kirli kontrol için, karşılaştırma (modellerin) her zaman her bir sindirim döngüsünde gerçekleşir.

  2. DOM güncellemesi : DOM işlemleri çok pahalıdır çünkü DOM'u değiştirmek CSS stillerini, mizanpajlarını da uygular ve hesaplar. Gereksiz DOM değişikliğinden kaydedilen süre, sanal DOM'yi ayırmak için harcanan süreden daha uzun olabilir.

İkinci nokta, çok fazla alana veya büyük listeye sahip olan gibi önemsiz modeller için daha da önemlidir. Karmaşık modelin bir alan değişikliği, yalnızca görünüm / şablon yerine bu alanı içeren DOM öğeleri için gereken işlemlerle sonuçlanır.


1
Aslında bazı makaleleri de okudum, bu yüzden şimdi (en azından genel olarak) nasıl çalıştığını, neden modelin kirli kontrolünden daha verimli olabileceğini anlamak istedim. Ve 1) Evet, modelleri karşılaştırmaz, ancak çok daha büyük sanal domları karşılaştırır 2) Modelin kirli kontrolü bize sadece ihtiyaç duyulan şeyleri güncelleme olanağı sağlar (Açısal'ın yaptığı gibi)
Daniil

Değişen bileşene karşılık gelen sanal DOM'un yalnızca bazı bölümlerinin karşılaştırılması gerektiğine inanıyorum, hiçbir şey değişmemiş olsa bile, kirli denetim her özet döngüsünde her kapsamda gerçekleşir. Büyük miktarda veri değiştiyse, Sanal DOM daha az verimli olur, ancak küçük veri değişikliği için olmaz.
Ocak'ta tungd

1
Angular'dan bahsetmişken, gözlemciler sindirim sırasında da durumu mutasyona uğratabildiğinden, $scope.$digestsindirim döngüsü başına birden çok kez yürütülür, bu nedenle kısmi sanal DOM ağacı karşılaştırmasının tek bir zamanına karşı tam veri karşılaştırmasının birden fazla zamanıdır.
Ocak'ta tungd

4
birçok akıllı geliştirici, sadece tarayıcıların kendilerini düzeltmek ve bir kez ve hepimiz DOM yavaşlığından kurtulmak için kombine dikkatimizi odaklamak yerine hilelerin "dağlarını" icat etti. tıpkı kanserin kendisini düzeltmek yerine kanserle başa çıkmanın ve hastanın yaşamını iyileştirmenin yollarını araştırmak için tüm insanlığın kaynaklarını kullanmak gibidir. Ridicules.
vsync

@vsync DOM'nun öğeleri ekranda görüntülemesi gerekiyor. Sanal bir DOM bunu yapmaz. İdeal performans gösteren bir DOM ile bile, sanal bir DOM oluşturmak daha hızlı olacaktır.
Jehan

75

Sanal DOM'un potansiyel gücünü gerçekten seviyorum (özellikle sunucu tarafı oluşturma), ancak tüm artıları ve eksileri bilmek istiyorum.

- OP

React, tek DOM manipülasyon kütüphanesi değildir. Ayrıntılı açıklama ve ölçütler içeren Auth0'dan bu makaleyi okuyarak alternatifleri anlamanızı tavsiye ediyorum . İstediğiniz gibi burada onların artılarını ve eksilerini vurgulayacağım:

React.js'nin Sanal DOM'u

resim açıklamasını buraya girin

Artıları

  • Hızlı ve verimli "farklı" algoritma
  • Birden çok kullanıcı arabirimi (JSX, hiperscript)
  • Mobil cihazlarda çalışacak kadar hafif
  • Çok çekiş ve zihniyet
  • Reaksiyon olmadan kullanılabilir (yani bağımsız bir motor olarak)

EKSİLERİ

  • DOM'un tam bellek içi kopyası (daha yüksek bellek kullanımı)
  • Statik ve dinamik elemanlar arasında ayrım yok

Ember.js 'Glimmer

resim açıklamasını buraya girin

Artıları

  • Hızlı ve verimli fark algoritması
  • Statik ve dinamik elemanlar arasındaki farklar
  • Ember API'sı ile% 100 uyumlu (mevcut kodunuzda büyük güncellemeler olmadan avantajlar elde edersiniz)
  • DOM'un hafif bellek içi gösterimi

EKSİLERİ

  • Yalnızca Ember'de kullanılması amaçlanmıştır
  • Yalnızca bir kullanıcı arabirimi kullanılabilir

Artımlı DOM

resim açıklamasını buraya girin

Artıları

  • Azaltılmış bellek kullanımı
  • Basit API
  • Birçok ön uç ve çerçeveyle kolayca entegre olur (başlangıçtan itibaren bir şablon motoru arka ucu anlamına gelir)

EKSİLERİ

  • Diğer kütüphaneler kadar hızlı değil (bu tartışılabilir, aşağıdaki kıyaslamalara bakın)
  • Daha az zihniyet ve topluluk kullanımı

ReactJS'nin DOM manipülasyonunun temsili bana çok az geliyor. ReactJS'nin sanal DOM'u gerçek DOM değil, tamamen değişen olandır - doğru mu? Özgün makaleye başvurulan makale referansları bakıyorum ve burada gördüğüm - teropa.info/images/onchange_vdom_change.svg . teropa.info/blog/2015/03/02/…
smile.al.d.way

35

İşte React ekip üyesi Sebastian Markbåge'ın biraz ışık tutan bir yorumu:

React, çıkışta fark yaratır (bilinen bir serileştirilebilir format olan DOM özellikleri). Bu, kaynak verilerin herhangi bir formatta olabileceği anlamına gelir. Değişmez veri yapıları olabilir ve kapakların içinde olabilir.

Açısal model referans şeffaflığını korumaz ve bu nedenle doğası gereği değiştirilebilir. Değişiklikleri izlemek için mevcut modeli değiştirirsiniz. Veri kaynağınız her seferinde değişmez veriler veya yeni bir veri yapısı ise (JSON yanıtı gibi) ne olur?

Kirli kontrol ve Object.observe kapatma kapsamı durumunda çalışmaz.

Bu iki şey işlevsel kalıplarla çok sınırlıdır.

Ek olarak, model karmaşıklığınız arttığında, kirli izleme yapmak giderek daha pahalı hale gelir. Ancak, React gibi yalnızca görsel ağaca farklılaşırsanız, o zaman o kadar fazla büyümez, çünkü ekranda herhangi bir noktada gösterebileceğiniz veri miktarı kullanıcı arayüzleri ile sınırlıdır. Pete'nin yukarıdaki bağlantısı daha fazla üstünlük sağlıyor.

https://news.ycombinator.com/item?id=6937668


2
Aslında son paragraf hakkında: yanlış olmalı: model sanal dom'dan daha büyüktür, çünkü her model değeri için (çoğu durumda) en az bir sanal dom öğesi (ve genellikle birden fazla) vardır. Gösterilmeyen modeli neden istiyorum?
Daniil

2
Önbelleğe alınmış koleksiyonları sayfalandırma.
kentor

-2

Sanal Dom tepki ile icat edilmez. HTML dom'in bir parçasıdır. Hafiftir ve tarayıcıya özgü uygulama ayrıntılarından ayrılmıştır.

Sanal DOM'u React'in HTML DOM'un yerel ve basitleştirilmiş kopyası olarak düşünebiliriz. React'in hesaplamalarını bu soyut dünyada yapmasına ve genellikle yavaş ve tarayıcıya özgü “gerçek” DOM işlemlerini atlamasına izin verir. Aslında DOM ve VIRTUAL DOM arasında büyük bir fark yoktur.

Sanal Dom'un neden kullanıldığı noktalar şunlardır ( ReactJS'de Sanal DOM kaynağı ):

Yaptığınızda:

document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
  1. Tarayıcının HTML'yi ayrıştırması gerekiyor
  2. ElementId öğesinin alt öğesini kaldırır
  3. DOM değerini yeni değerle günceller
  4. Ebeveyn ve çocuk için css'i yeniden hesaplayın
  5. Düzeni güncelleyin, yani her öğe ekranda tam olarak koordine olur
  6. Oluşturma ağacını gezdirin ve tarayıcı ekranında boyayın

CSS ve değiştirilmiş düzenlerin yeniden hesaplanması karmaşık algoritma kullanır ve performansı etkiler.

Yanı sıra DOM özellikleri yani güncelleme. değerler. Bunu bir algoritma izler.

Şimdi, DOM'u doğrudan 10 kez güncellerseniz, yukarıdaki tüm adımların tek tek çalışacağını ve DOM algoritmalarının güncellenmesinin DOM değerlerini güncellemesinin zaman alacağını varsayalım.

Real DOM'nin sanal DOM'dan daha yavaş olmasının nedeni budur.


3
Örnek hakkında, dom'u doğrudan veya sanal dom üzerinden değiştiriyorsanız, son olarak her iki durumda da domu değiştirirsiniz.
Magallanes

Evet, her iki durumda da dom'u güncelliyoruz, ancak sanal dom durumunda, yalnızca anahtar (benzersiz olarak algoritma tarafından reaksiyondan farklıdır) alanı veya öğe etiketini günceller. Oysa dom güncellemeleri güncellenir veya tüm dom tamamen yenilenir.
Hemant Nagarkoti

11
Bu makaleyi hackernoon.com/virtual-dom-in-reactjs-43a3fdb1d130 adresinden gördüm . Belki de yazar değilseniz kaynağı belirtmeniz daha iyi olur.
Jinggang

2
"Bu yüzden Real DOM sanal DOM'dan daha yavaştır." Hayır efendim, yanılıyorsunuz.
Roecrew
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.