Sanal DOM Düğümleri
Sanal DOM Nedir
Sanal DOM ağacı, bir DOM ağacını tanımlayan bir JavaScript veri yapısıdır. İç içe geçmiş sanal DOM düğümlerinden oluşur ve aynı zamanda vnode olarak da bilinir.
Bir sanal DOM ağacı ilk kez render edildiğinde, yapısına uygun bir DOM ağacı oluşturmak için bir şablon olarak kullanılır.
Tipik olarak, sanal DOM ağaçları daha sonra her render döngüsünde yeniden oluşturulur; bu genellikle olay işleyicilerine veya veri değişikliklerine yanıt olarak gerçekleşir. Mithril.js, bir vnode ağacını önceki sürümüyle karşılaştırır ve yalnızca değişikliklerin olduğu yerlerde DOM öğelerini değiştirir.
Vnode'ları bu kadar sık yeniden oluşturmak israf gibi görünebilir, ancak modern JavaScript motorlarının bir milisaniyeden daha kısa sürede yüz binlerce nesne oluşturabileceği ortaya çıkmıştır. Öte yandan, DOM'u değiştirmek vnode oluşturmaktan çok daha maliyetlidir.
Bu nedenle, Mithril.js, DOM güncellemelerinin miktarını en aza indirmek için gelişmiş ve yüksek derecede optimize edilmiş bir sanal DOM karşılaştırma algoritması kullanır. Mithril.js ayrıca, neredeyse yerel veri yapısı erişim performansı için JavaScript motorları tarafından derlenen özenle hazırlanmış vnode veri yapıları oluşturur. Ek olarak, Mithril.js, vnode'ları oluşturan işlevi de agresif bir şekilde optimize eder.
Mithril.js'nin her render'da tüm sanal DOM ağacını yeniden oluşturan bir render modelini desteklemek için bu kadar büyük çaba göstermesinin nedeni, kullanıcı arayüzü karmaşıklığını yönetmeyi önemli ölçüde kolaylaştıran bildirimsel bir anlık mod API'si sağlamaktır.
Anlık modun neden bu kadar önemli olduğunu anlamak için DOM API'sini ve HTML'yi inceleyelim. DOM API'si emirli bir saklama modu API'sidir ve 1. bir DOM ağacını yordamsal olarak bir araya getirmek için kesin talimatlar yazmayı ve 2. bu ağacı güncellemek için diğer talimatları yazmayı gerektirir. DOM API'sinin emirli yapısı, kodunuzu mikro düzeyde optimize etmek için birçok fırsatınız olduğu anlamına gelir, ancak aynı zamanda hata yapma olasılığınızın daha yüksek olduğu ve kodu anlamayı zorlaştırma olasılığınızın daha yüksek olduğu anlamına gelir.
Buna karşılık, HTML anlık mod render sistemine daha yakındır. HTML ile, bir alt öğeyi bir üst öğeye eklemeyi unutma, son derece derin ağaçları işlerken yığın aşımlarına rastlama vb. endişesi duymadan, bir DOM ağacını daha doğal ve okunabilir bir şekilde yazabilirsiniz.
Sanal DOM, kullanıcı arayüzünü rastgele veri değişiklikleriyle verimli bir şekilde senkronize etmek için birden fazla DOM API çağrısını manuel olarak yazmak zorunda kalmadan dinamik DOM ağaçları yazmanıza olanak tanıyarak HTML'den bir adım öteye gider.
Temel Bilgiler
Sanal DOM düğümleri veya vnode'lar, DOM öğelerini (veya DOM'un parçalarını) temsil eden JavaScript nesneleridir. Mithril.js'nin sanal DOM motoru, bir DOM ağacı üretmek için bir vnode ağacını kullanır.
Vnode'lar m()
hyperscript yardımcı programı ile oluşturulur:
m('div', { id: 'test' }, 'hello');
Hyperscript ayrıca bileşenleri de kullanabilir:
// bir bileşen tanımla
var ExampleComponent = {
view: function (vnode) {
return m('div', vnode.attrs, ['Hello ', vnode.children]);
},
};
// kullan
m(ExampleComponent, { style: 'color:red;' }, 'world');
// eşdeğer HTML:
// <div style="color:red;">Hello world</div>
Yapı
Sanal DOM düğümleri veya vnode'lar, bir öğeyi (veya DOM'un parçalarını) temsil eden JavaScript nesneleridir ve aşağıdaki özelliklere sahiptir:
Özellik | Tür | Açıklama |
---|---|---|
tag | String|Object | Bir DOM öğesinin nodeName 'idir. Bir vnode bir parçaysa [ dizesi, bir metin vnode'uysa # veya güvenilen bir HTML vnode'uysa < dizesi de olabilir. Ek olarak, bir bileşen de olabilir. |
key | String? | Bir DOM öğesini bir veri dizisindeki ilgili öğesine eşlemek için kullanılan değer. |
attrs | Object? | DOM özniteliklerinin, olayların, özelliklerin ve yaşam döngüsü yöntemlerinin bir karma eşlemesi. |
children | (Array|String|Number|Boolean)? | Çoğu vnode türünde, children özelliği bir vnode dizisidir. Metin ve güvenilen HTML vnode'ları için, children özelliği bir dize, bir sayı veya bir boole değeridir. |
text | (String|Number|Boolean)? | Bu, bir vnode'un tek alt öğesi olarak bir metin düğümü içeriyorsa children yerine kullanılır. Bu, performans nedenleriyle yapılır. Bileşen vnode'ları, tek alt öğesi olarak bir metin düğümü olsa bile text özelliğini asla kullanmaz. |
dom | Element? | Vnode'a karşılık gelen öğeyi gösterir. Bu özellik, oninit yaşam döngüsü yönteminde undefined 'dır. Parçalarda ve güvenilen HTML vnode'larında, dom aralıktaki ilk öğeyi gösterir. |
domSize | Number? | Bu yalnızca parça ve güvenilen HTML vnode'larında ayarlanır ve diğer tüm vnode türlerinde undefined 'dır. Vnode'un temsil ettiği DOM öğelerinin sayısını tanımlar (dom özelliği tarafından başvurulan öğeden başlayarak). |
state | Object? | Yeniden oluşturmalar arasında kalıcı olan bir nesne. Gerektiğinde çekirdek motoru tarafından sağlanır. POJO (Plain Old JavaScript Object) bileşen vnode'larında, state prototip olarak bileşen nesnesinden/sınıfından devralır. Sınıf bileşen vnode'larında sınıfın bir örneğidir. Kapatma bileşenlerinde kapatma tarafından döndürülen nesnedir. |
events | Object? | Yeniden oluşturmalar arasında kalıcı olan ve olay işleyicilerini depolayan bir nesne, böylece DOM API'si kullanılarak kaldırılabilirler. events özelliği, tanımlanmış olay işleyicisi yoksa undefined 'dır. Bu özellik yalnızca Mithril.js tarafından dahili olarak kullanılır, kullanmayın veya değiştirmeyin. |
instance | Object? | Bileşenler için, view tarafından döndürülen değer için bir depolama konumu. Bu özellik yalnızca Mithril.js tarafından dahili olarak kullanılır, kullanmayın veya değiştirmeyin. |
Vnode Türleri
Bir vnode'un tag
özelliği türünü belirler. Beş vnode türü vardır:
Vnode türü | Örnek | Açıklama |
---|---|---|
Öğe | {tag: "div"} | Bir DOM öğesini temsil eder. |
Parça | {tag: "[", children: []} | Üst DOM öğesi, parçada bulunmayan başka öğeler de içerebilen bir DOM öğesi listesidir. |
Metin | {tag: "#", children: ""} | Bir DOM metin düğümünü temsil eder. |
Güvenilen HTML | {tag: "<", children: "<br>"} | Bir HTML dizesinden oluşan bir DOM öğesi listesini temsil eder. |
Bileşen | {tag: ExampleComponent} | tag , bir view yöntemi olan bir JavaScript nesnesiyse, vnode bileşeni render ederek oluşturulan DOM'u temsil eder. |
Sanal DOM ağacındaki her şey, metin dahil bir vnode'dur. m()
yardımcı programı, children
bağımsız değişkenini otomatik olarak normalleştirir ve dizeleri metin vnode'larına ve iç içe geçmiş dizileri parça vnode'larına dönüştürür.
Yalnızca öğe etiket adları ve bileşenler, m()
işlevinin ilk bağımsız değişkeni olabilir. Başka bir deyişle, [
, #
ve <
, m()
için geçerli selector
bağımsız değişkenleri değildir. Güvenilen HTML vnode'ları m.trust()
aracılığıyla oluşturulabilir.
Monomorfik Sınıf
mithril/render/vnode
modülü, Mithril.js tarafından tüm vnode'ları oluşturmak için kullanılır. Bu, modern JavaScript motorlarının vnode'ları her zaman aynı gizli sınıfa derleyerek sanal dom karşılaştırmasını optimize edebilmesini sağlar.
Vnode'lar üreten kitaplıklar oluştururken, yüksek düzeyde render performansı sağlamak için çıplak JavaScript nesneleri yazmak yerine bu modülü kullanmalısınız.
Anti-Desenlerden Kaçının
Vnode'ları Yeniden Kullanmaktan Kaçının
Vnode'ların, DOM'un belirli bir anındaki durumunu temsil etmesi gerekir. Mithril.js'nin render motoru, yeniden kullanılan bir vnode'un değişmediğini varsayar, bu nedenle önceki bir render'da kullanılan bir vnode'u değiştirmek belirsiz davranışa neden olur.
Bir farkı önlemek için vnode'ları yerinde yeniden kullanmak mümkün olsa da, onbeforeupdate
kullanmak daha iyidir.
Model Verilerini Doğrudan Öznitelikler Aracılığıyla Bileşenlere İletmekten Kaçının
key
özelliği, veri modelinizde Mithril.js'nin anahtar mantığıyla çelişebilir ve modelinizin kendisi, onupdate
veya onremove
gibi bir yaşam döngüsü kancasıyla aynı adı paylaşan bir yönteme sahip değiştirilebilir bir örnek olabilir. Örneğin, bir model özelleştirilebilir bir renk anahtarını temsil etmek için bir key
özelliği kullanabilir. Bu değiştiğinde, bileşenlerin yanlış veriler almasına, beklenmedik şekilde konum değiştirmesine veya diğer beklenmedik, istenmeyen davranışlara yol açabilir. Bunun yerine, Mithril.js'nin yanlış yorumlamaması için (ve böylece daha sonra potansiyel olarak değiştirebilir veya prototip yöntemlerini çağırabilirsiniz) bir öznitelik olarak iletin:
// Veri modeli
var users = [
{ id: 1, name: 'John', key: 'red' },
{ id: 2, name: 'Mary', key: 'blue' },
];
// Daha sonra...
users[0].key = 'yellow';
// KAÇININ
users.map(function (user) {
// John'un bileşeni yok edilecek ve yeniden oluşturulacak
return m(UserComponent, user);
});
// TERCİH EDİN
users.map(function (user) {
// Anahtar özellikle çıkarılır: veri modeline kendi özelliği verilir
return m(UserComponent, { key: user.id, model: user });
});
Görünüm Yöntemlerinde İfadelerden Kaçının
Görünüm yöntemlerindeki JavaScript ifadeleri genellikle HTML ağacının doğal iç içe yapısını değiştirmeyi gerektirir. Bu durum kodu daha karmaşık ve okunması zor hale getirir.
// KAÇININ
var BadListComponent = {
view: function (vnode) {
var list = [];
for (var i = 0; i < vnode.attrs.items.length; i++) {
list.push(m('li', vnode.attrs.items[i]));
}
return m('ul', list);
},
};
Bunun yerine, koşul operatörü gibi JavaScript ifadelerini ve liste benzeri yapılar için dizi metotlarını kullanmayı tercih edin.
// TERCİH EDİN
var BetterListComponent = {
view: function (vnode) {
return m(
'ul',
vnode.attrs.items.map(function (item) {
return m('li', item);
})
);
},
};