m(selector, attributes, children)
Açıklama
Mithril.js'de bir HTML öğesini temsil eder.
m('div.foo', { style: { color: 'red' } }, 'hello');
// şu HTML olarak işlenir:
// <div class="foo" style="color: red">hello</div>
Ayrıca, eşdeğer hyperscript çağrılarına dönüştürmek için Babel kullanarak JSX adlı HTML'e benzeyen bir sözdizimi de kullanabilirsiniz. Bu, yukarıdakiyle aynıdır.
<div class="foo" style="color: red">
hello
</div>
İmza
vnode = m(selector, attrs, children)
Argüman | Tür | Gerekli | Açıklama |
---|---|---|---|
selector | String|Object|Function | Evet | Bir CSS seçicisi veya bir bileşen |
attrs | Object | Hayır | HTML nitelikleri veya öğe özellikleri |
children | Array<Vnode>|String|Number|Boolean | Hayır | Çocuk vnode'ları. Splat argümanları olarak yazılabilir. |
döndürür | Vnode | Bir vnode |
Nasıl Çalışır
Mithril.js, JavaScript sözdizimiyle HTML yapıları oluşturmayı sağlayan m()
adlı bir hyperscript fonksiyonu sunar. Bir selector
dizesi (gerekli), bir attrs
nesnesi (isteğe bağlı) ve bir children
dizisi (isteğe bağlı) kabul eder.
m('div', { id: 'box' }, 'hello');
// şu HTML olarak işlenir:
// <div id="box">hello</div>
m()
fonksiyonu aslında bir DOM öğesi döndürmez. Bunun yerine, oluşturulacak DOM öğesini temsil eden bir JavaScript nesnesi olan bir sanal DOM düğümü veya vnode döndürür.
// bir vnode
var vnode = {
tag: 'div',
attrs: { id: 'box' },
children: [
/*...*/
],
};
Bir vnode'u gerçek bir DOM öğesine dönüştürmek için m.render()
fonksiyonunu kullanın:
m.render(document.body, m('br')); // <body> içine bir <br> ekler
m.render()
fonksiyonunu birden çok kez çağırmak, DOM ağacını her seferinde sıfırdan yeniden oluşturmaz. Bunun yerine, her çağrı yalnızca sanal DOM ağacını yansıtmak için gerekli olduğunda DOM ağacında değişiklik yapar. DOM'u sıfırdan yeniden oluşturmak çok maliyetli olduğundan ve diğer şeylerin yanı sıra giriş odağı kaybı gibi sorunlara neden olduğundan, bu davranış tercih edilir. Buna karşılık, DOM'u yalnızca gerektiğinde güncellemek nispeten çok daha hızlıdır ve birden çok kullanıcı hikayesini işleyen karmaşık kullanıcı arayüzlerini korumayı kolaylaştırır.
Esneklik
m()
fonksiyonu hem polimorfik hem de değişken sayıda argüman alabilendir. Diğer bir deyişle, farklı türde girdi parametrelerini kabul edebilir.
// basit etiket
m('div'); // <div></div>
// özellikler ve çocuklar isteğe bağlıdır
m('a', { id: 'b' }); // <a id="b"></a>
m('span', 'hello'); // <span>hello</span>
// çocuk düğümleri olan etiket
m('ul', [
// <ul>
m('li', 'hello'), // <li>hello</li>
m('li', 'world'), // <li>world</li>
]); // </ul>
// dizi isteğe bağlıdır
m(
'ul', // <ul>
m('li', 'hello'), // <li>hello</li>
m('li', 'world') // <li>world</li>
); // </ul>
CSS Seçicileri
m()
'nin ilk argümanı, bir HTML öğesini tanımlayabilen herhangi bir CSS seçicisi olabilir. #
(id), .
(sınıf) ve []
(nitelik) sözdiziminin herhangi bir geçerli CSS kombinasyonunu kabul eder.
m('div#hello');
// <div id="hello"></div>
m('section.container');
// <section class="container"></section>
m('input[type=text][placeholder=Name]');
// <input type="text" placeholder="Name" />
m("a#exit.external[href='https://example.com']", 'Leave');
// <a id="exit" class="external" href="https://example.com">Leave</a>
Etiket adını atlarsanız, Mithril.js bir div
etiketi olduğunu varsayar.
m('.box.box-bordered'); // <div class="box box-bordered"></div>
Genellikle, değeri değişmeyen statik nitelikler için CSS seçicileri, dinamik nitelik değerleri için ise bir özellik nesnesi kullanılması önerilir.
var currentURL = '/';
m(
'a.link[href=/]',
{
class: currentURL === '/' ? 'selected' : '',
},
'Home'
);
// şu HTML olarak işlenir:
// <a href="/" class="link selected">Home</a>
İkinci Argüman Olarak Geçirilen Özellikler
İsteğe bağlı olan ikinci argüman ile özellikler, olaylar ve yaşam döngüsü kancaları aktarılabilir (detaylar için sonraki bölümlere bakınız).
m("button", {
class: "my-button",
onclick: function() {/* ... */},
oncreate: function() {/* ... */}
})
Böyle bir özelliğin değeri null
veya undefined
ise, özellik yokmuş gibi davranılır.
m()
'nin hem birinci hem de ikinci argümanında sınıf adları varsa, beklendiği gibi birleştirilirler. İkinci argümandaki sınıfın değeri null
veya undefined
ise, yoksayılır.
Başka bir özellik hem birinci hem de ikinci argümanda mevcutsa, null
veya undefined
olsa bile ikincisi önceliklidir.
DOM Özellikleri
Mithril.js, özellikleri çözümlemek için hem JavaScript API'sini hem de DOM API'sini (setAttribute
) kullanır. Bu, niteliklere başvurmak için her iki sözdizimini de kullanabileceğiniz anlamına gelir.
Örneğin, JavaScript API'sinde readonly
özelliğine element.readOnly
adı verilir (büyük harfe dikkat edin). Mithril.js'de aşağıdakilerin tümü desteklenir:
m('input', { readonly: true }); // küçük harf
m('input', { readOnly: true }); // büyük harf
m('input[readonly]');
m('input[readOnly]');
Bu, özel HTML öğelerini de kapsar. Örneğin, Mithril.js içinde A-Frame kullanabilirsiniz, sorun değil!
m('a-scene', [
m('a-box', {
position: '-1 0.5 -3',
rotation: '0 45 0',
color: '#4CC3D9',
}),
m('a-sphere', {
position: '0 1.25 -5',
radius: '1.25',
color: '#EF2D5E',
}),
m('a-cylinder', {
position: '1 0.75 -3',
radius: '0.5',
height: '1.5',
color: '#FFC65D',
}),
m('a-plane', {
position: '0 0 -4',
rotation: '-90 0 0',
width: '4',
height: '4',
color: '#7BC8A4',
}),
m('a-sky', {
color: '#ECECEC',
}),
]);
Özel öğeler için, nesneler, sayılar veya başka bir dize olmayan değer olması durumunda özellikleri otomatik olarak dizgeleştirmez. Bu nedenle, bir elem.whitelist
dizi alıcı/ayarlayıcı özelliğine sahip bazı özel öğeleriniz my-special-element
olduğunu varsayarsak, bunu yapabilirsiniz ve beklendiği gibi çalışır:
m('my-special-element', {
whitelist: [
'https://example.com',
'https://neverssl.com',
'https://google.com',
],
});
Bu öğeler için sınıflarınız veya kimlikleriniz varsa, kısaltmalar beklendiği gibi çalışmaya devam eder. Başka bir A-Frame örneği çekmek için:
// Bu ikisi eşdeğerdir
m('a-entity#player');
m('a-entity', { id: 'player' });
Yaşam döngüsü özellikleri, onevent
işleyicileri, key
ler, class
ve style
gibi sihirli semantiğe sahip tüm özelliklerin normal HTML öğeleri için olduğu gibi aynı şekilde ele alındığını unutmayın.
Stil Özelliği
Mithril.js, geçerli style
değerleri olarak hem dizeleri hem de nesneleri destekler. Başka bir deyişle, aşağıdakilerin tümü desteklenir:
m('div', { style: 'background:red;' });
m('div', { style: { background: 'red' } });
m('div[style=background:red]');
style
özelliği olarak bir dize kullanmak, yeniden çizme işleminde öğedeki tüm satır içi stilleri üzerine yazar; yalnızca değişen CSS kurallarını değil.
Hem tireli CSS özellik adlarını (background-color
gibi) hem de deve kasalı DOM style
özellik adlarını (backgroundColor
gibi) kullanabilirsiniz. Tarayıcınız destekliyorsa CSS özel özelliklerini de tanımlayabilirsiniz.
Mithril.js, sayı değerlerine birim eklemeye çalışmaz. Sadece onları dizgeleştirir.
Olaylar
Mithril.js, on${event}
özelliği tanımlanmamış olsa bile, touchstart
gibi tüm DOM olayları için olay dinleyici (event handler) tanımlamayı destekler.
function doSomething(e) {
console.log(e);
}
m('div', { onclick: doSomething });
Mithril.js, fonksiyonları ve EventListener nesnelerini kabul eder. Bu nedenle bu da işe yarayacaktır:
var clickListener = {
handleEvent: function (e) {
console.log(e);
},
};
m('div', { onclick: clickListener });
Varsayılan olarak, hyperscript ile eklenmiş bir olay tetiklendiğinde, bu, olay geri aramanız döndükten sonra Mithril.js'nin otomatik yeniden çizimini tetikleyecektir (doğrudan m.render
yerine m.mount
veya m.route
kullandığınızı varsayarak). Özellikle tek bir olay için otomatik yeniden çizimi, üzerinde e.redraw = false
ayarlayarak devre dışı bırakabilirsiniz:
m('div', {
onclick: function (e) {
// Otomatik yeniden çizimi önle
e.redraw = false;
},
});
Özellikler
Mithril.js, <select>
öğesinin selectedIndex
ve value
gibi özellikleri aracılığıyla erişilebilen DOM işlevselliğini destekler.
m('select', { selectedIndex: 0 }, [
m('option', 'Option A'),
m('option', 'Option B'),
]);
Bileşenler
Bileşenler, mantığı bir birimde kapsülleyip onu bir öğe gibi kullanmanıza olanak tanır. Büyük ve ölçeklenebilir uygulamalar geliştirmek için temel oluştururlar.
Bir bileşen, bir view
yöntemi içeren herhangi bir JavaScript nesnesidir. Bir bileşeni kullanmak için, bir CSS seçici dizesi geçirmek yerine bileşeni m()
'ye ilk argüman olarak geçirin. Aşağıdaki örnekte gösterildiği gibi, özellikleri ve çocukları tanımlayarak bileşene argümanlar geçirebilirsiniz.
// bir bileşen tanımla
var Greeter = {
view: function (vnode) {
return m('div', vnode.attrs, ['Hello ', vnode.children]);
},
};
// tüket
m(Greeter, { style: 'color:red;' }, 'world');
// şu HTML olarak işlenir:
// <div style="color:red;">Hello world</div>
Bileşenler hakkında daha fazla bilgi edinmek için bileşenler sayfasına bakın.
Yaşam Döngüsü Yöntemleri
Vnode'lar ve bileşenler, bir DOM öğesinin ömrü boyunca çeşitli noktalarda çağrılan yaşam döngüsü yöntemlerine (aynı zamanda kancalar olarak da bilinir) sahip olabilir. Mithril.js tarafından desteklenen yaşam döngüsü yöntemleri şunlardır: oninit
, oncreate
, onupdate
, onbeforeremove
, onremove
ve onbeforeupdate
.
Yaşam döngüsü yöntemleri, DOM olay işleyicileri gibi tanımlanır, ancak bir Event nesnesi yerine vnode'u bir argüman olarak alır:
function initialize(vnode) {
console.log(vnode);
}
m('div', { oninit: initialize });
Kanca | Açıklama |
---|---|
oninit(vnode) | Bir vnode gerçek bir DOM öğesine dönüştürülmeden önce çalışır. |
oncreate(vnode) | Bir vnode DOM'a eklendikten sonra çalışır. |
onupdate(vnode) | DOM öğesi belgeye bağlıyken her yeniden çizim gerçekleştiğinde çalışır. |
onbeforeremove(vnode) | Bir DOM öğesi belgeden kaldırılmadan önce çalışır. Eğer bir Promise döndürülürse, Mithril.js DOM öğesini yalnızca Promise tamamlandıktan sonra ayırır. Bu yöntem yalnızca üst DOM öğesinden ayrılan öğede tetiklenir, ancak alt öğelerinde tetiklenmez. |
onremove(vnode) | Bir DOM öğesi belgeden kaldırılmadan önce çalışır. Bir onbeforeremove kancası tanımlanmışsa, onremove , done çağrıldıktan sonra çağrılır. Bu yöntem, üst öğesinden ayrılan öğede ve tüm alt öğelerinde tetiklenir. |
onbeforeupdate(vnode, old) | onupdate 'den önce çalışır ve false döndürürse, öğe ve tüm alt öğeleri için bir farkı önler. |
Yaşam döngüsü yöntemleri hakkında daha fazla bilgi edinmek için yaşam döngüsü yöntemleri sayfasına bakın.
Anahtarlar
Bir listedeki vnode'lar, vnode listesini oluşturan model verileri değiştiğinde DOM öğesinin kimliğini yönetmek için kullanılabilen key
adlı özel bir özelliğe sahip olabilir.
Tipik olarak, key
, veri dizisindeki nesnelerin benzersiz tanımlayıcı alanı olmalıdır.
var users = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Mary' },
];
function userInputs(users) {
return users.map(function (u) {
return m('input', { key: u.id }, u.name);
});
}
m.render(document.body, userInputs(users));
Bir anahtar kullanmak, users
dizisi karıştırıldığında ve görünüm yeniden oluşturulduğunda, giriş alanlarının doğru odağı ve DOM durumunu koruyarak aynı sırada kalmasını sağlar.
Anahtarlar hakkında daha fazla bilgi edinmek için anahtarlar sayfasına bakın.
SVG ve MathML
Mithril.js, SVG'yi tam olarak destekler. Xlink de desteklenir, ancak Mithril.js'nin v1.0 öncesi sürümlerinden farklı olarak, ad alanı açıkça tanımlanmalıdır:
m('svg', [m("image[xlink:href='image.gif']")]);
MathML de tam olarak desteklenir.
Şablonları Dinamik Hale Getirme
İç içe geçmiş vnode'lar sadece düz JavaScript ifadeleri olduğundan, bunları değiştirmek için JavaScript olanaklarını kullanabilirsiniz.
Dinamik Metin
var user = { name: 'John' };
m('.name', user.name); // <div class="name">John</div>
Döngüler
Veri listelerini yinelemek için map
gibi Array
yöntemlerini kullanın.
var users = [{ name: 'John' }, { name: 'Mary' }];
m(
'ul',
users.map(function (u) {
// <ul>
return m('li', u.name); // <li>John</li>
// <li>Mary</li>
})
); // </ul>
// ES6+:
// m("ul", users.map(u =>
// m("li", u.name)
// ))
Koşullar
Bir görünümde içeriği koşullu olarak ayarlamak için üçlü operatörü kullanın.
var isError = false;
m('div', isError ? 'An error occurred' : 'Saved'); // <div>Saved</div>
JavaScript ifadelerinde if
veya for
gibi JavaScript ifadelerini kullanamazsınız. Bu ifadelerden tamamen kaçınmak ve bunun yerine, şablonların yapısını doğrusal ve bildirimsel tutmak için yukarıdaki yapıları özel olarak kullanmak tercih edilir.
HTML'yi Dönüştürme
Mithril.js'de, iyi biçimlendirilmiş HTML geçerli JSX'tir. Bağımsız olarak üretilmiş bir HTML dosyasını JSX kullanarak bir projeye entegre etmek için kopyala-yapıştırmadan başka çok az çaba gerekir.
Hyperscript kullanırken, kod çalıştırılmadan önce HTML'yi hyperscript sözdizimine dönüştürmek gerekir. Bunu kolaylaştırmak için HTML-to-Mithril-template dönüştürücüyü kullanabilirsiniz.
Anti-Desenlerden Kaçının
Mithril.js esnek olmasına rağmen, bazı kod desenleri önerilmez:
Dinamik Seçicilerden Kaçının
Farklı DOM öğeleri, farklı özelliklere ve genellikle farklı davranışlara sahiptir. Bir seçiciyi yapılandırılabilir yapmak, bileşenin iç yapısının dışarıya açılmasına neden olabilir.
// KAÇININ
var BadInput = {
view: function (vnode) {
return m('div', [m('label'), m(vnode.attrs.type||'input')]);
},
};
Dinamik seçiciler kullanmak yerine, her geçerli durumu açıkça kodlamanız veya değişken kısımları yeniden düzenlemeniz önerilir.
// Açık kodu TERCİH EDİN
var BetterInput = {
view: function (vnode) {
return m('div', [m('label', vnode.attrs.title), m('input')]);
},
};
var BetterSelect = {
view: function (vnode) {
return m('div', [m('label', vnode.attrs.title), m('select')]);
},
};
// Değişkenliği yeniden düzenlemeyi TERCİH EDİN
var BetterLabeledComponent = {
view: function (vnode) {
return m('div', [m('label', vnode.attrs.title), vnode.children]);
},
};
Görünümlerin Dışında Vnode Oluşturmaktan Kaçının
Bir yeniden çizim, önceki render'dakiyle kesinlikle eşit olan bir vnode ile karşılaştığında, atlanır ve içeriği güncellenmez. Bu, performans optimizasyonu için bir fırsat gibi görünse de, bundan kaçınılmalıdır çünkü bu, o düğümün ağacındaki dinamik değişiklikleri önler - bu, yeniden çizimde tetiklenemeyen aşağı akış yaşam döngüsü yöntemleri gibi yan etkilere yol açar. Bu bağlamda, Mithril.js vnode'ları değişmezdir: Yeni vnode'lar eski vnode'larla karşılaştırılır; vnode'lar üzerinde yapılan değişiklikler saklanmaz.
Bileşen belgeleri daha fazla ayrıntı ve bu anti-desenin bir örneğini içerir.