m(selector, attributes, children)
Popis
Reprezentuje HTML prvek ve virtuálním DOM Mithril.js.
m('div.foo', { style: { color: 'red' } }, 'hello');
// Vykreslí do tohoto HTML:
// <div class="foo" style="color: red">hello</div>
Můžete také použít syntaxi podobnou HTML, nazývanou JSX, s použitím Babelu pro převod na ekvivalentní volání hyperscriptu. Následující kód je ekvivalentní výše uvedenému.
<div class="foo" style="color: red">
hello
</div>
Signatura
vnode = m(selector, attrs, children)
Argument | Typ | Povinný | Popis |
---|---|---|---|
selector | String|Object|Function | Ano | CSS selektor nebo komponenta |
attrs | Object | Ne | HTML atributy nebo vlastnosti elementu |
children | Array<Vnode>|String|Number|Boolean | Ne | Potomci vnode. Lze je zapsat jako splat argumenty |
returns | Vnode | Vnode |
Jak to funguje
Mithril.js poskytuje hyperscriptovou funkci m()
, která umožňuje vyjádřit jakoukoli HTML strukturu pomocí syntaxe JavaScriptu. Přijímá řetězec selector
(povinný), objekt attrs
(volitelný) a pole children
(volitelné).
m('div', { id: 'box' }, 'hello');
// Vykreslí do tohoto HTML:
// <div id="box">hello</div>
Funkce m()
ve skutečnosti nevrací DOM prvek. Místo toho vrací virtuální DOM uzel, neboli vnode. To je objekt JavaScriptu, který reprezentuje DOM element, který má být vytvořen.
// vnode
var vnode = {
tag: 'div',
attrs: { id: 'box' },
children: [
/*...*/
],
};
Pro transformaci vnode na skutečný DOM element použijte funkci m.render()
:
m.render(document.body, m('br')); // vloží <br> do <body>
Opakované volání m.render()
nevytváří DOM strom od začátku při každém volání. Místo toho každé volání provede změny v DOM stromu pouze tehdy, pokud je to nezbytné k zrcadlení virtuálního DOM stromu předaného do volání. Toto chování je žádoucí, protože opětovné vytváření DOM od začátku je nákladné a způsobuje problémy, například ztrátu zaměření vstupu. Aktualizace DOM pouze tam, kde je to nutné, je relativně mnohem rychlejší a usnadňuje údržbu složitých uživatelských rozhraní, která zpracovávají různé uživatelské scénáře.
Flexibilita
Funkce m()
je polymorfní a variadická. Jinými slovy, je velmi flexibilní v tom, co očekává jako vstupní parametry.
// jednoduchý tag
m('div'); // <div></div>
// atributy a potomci jsou volitelné
m('a', { id: 'b' }); // <a id="b"></a>
m('span', 'hello'); // <span>hello</span>
// tag s potomky
m('ul', [
// <ul>
m('li', 'hello'), // <li>hello</li>
m('li', 'world'), // <li>world</li>
]); // </ul>
// pole je volitelné
m(
'ul', // <ul>
m('li', 'hello'), // <li>hello</li>
m('li', 'world') // <li>world</li>
); // </ul>
CSS selektory
První argument m()
může být jakýkoli CSS selektor, který může popsat HTML element. Přijímá jakékoli platné CSS kombinace syntaxe #
(id), .
(třída) a []
(atribut).
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>
Pokud vynecháte název tagu, Mithril.js předpokládá tag div
.
m('.box.box-bordered'); // <div class="box box-bordered"></div>
Obvykle se doporučuje používat CSS selektory pro statické atributy (tj. atributy, jejichž hodnota se nemění), a objekt atributů pro dynamické hodnoty atributů.
var currentURL = '/';
m(
'a.link[href=/]',
{
class: currentURL === '/' ? 'selected' : '',
},
'Home'
);
// Vykreslí do tohoto HTML:
// <a href="/" class="link selected">Home</a>
Atributy předané jako druhý argument
Můžete předat atributy, vlastnosti, události a hooky životního cyklu v druhém, volitelném argumentu (viz další části pro podrobnosti).
m("button", {
class: "my-button",
onclick: function() {/* ... */},
oncreate: function() {/* ... */}
})
Pokud má atribut hodnotu null
nebo undefined
, chová se to, jako by nebyl definován.
Pokud jsou názvy tříd v prvním i druhém argumentu m()
, jsou sloučeny dohromady. Pokud je hodnota třídy v druhém argumentu null
nebo undefined
, je ignorována.
Pokud je jiný atribut přítomen v prvním i druhém argumentu, druhý má přednost, i když je null
nebo undefined
.
DOM atributy
Mithril.js používá pro práci s atributy JavaScript API i DOM API (setAttribute
). To znamená, že můžete použít obě syntaxe k odkazování na atributy.
Například v JavaScript API se atribut readonly
nazývá element.readOnly
(všimněte si velkého písmene). V Mithril.js jsou podporovány všechny následující:
m('input', { readonly: true }); // lowercase
m('input', { readOnly: true }); // uppercase
m('input[readonly]');
m('input[readOnly]');
To zahrnuje i vlastní elementy. Například můžete použít A-Frame v rámci Mithril.js.
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',
}),
]);
Pro vlastní elementy automaticky nepřevádí vlastnosti na řetězce, pokud se jedná o objekty, čísla nebo jiné neřetězcové hodnoty. Takže za předpokladu, že máte nějaký vlastní element my-special-element
, který má vlastnost elem.whitelist
getter/setter pole, můžete to udělat a bude to fungovat.
m('my-special-element', {
whitelist: [
'https://example.com',
'https://neverssl.com',
'https://google.com',
],
});
Pokud máte třídy nebo ID pro tyto elementy, zkratky stále fungují. Chcete-li použít další příklad A-Frame:
// Tyto dva zápisy jsou ekvivalentní
m('a-entity#player');
m('a-entity', { id: 'player' });
Všimněte si, že všechny vlastnosti s magickou sémantikou, jako jsou atributy životního cyklu, obslužné rutiny onevent
, key
, class
a style
, jsou stále zpracovávány stejným způsobem jako u normálních HTML elementů.
Atribut Style
Mithril.js podporuje řetězce i objekty jako platné hodnoty style
. Jsou podporovány všechny následující zápisy:
m('div', { style: 'background:red;' });
m('div', { style: { background: 'red' } });
m('div[style=background:red]');
Použití řetězce jako style
by přepsalo všechny inline styly v elementu, pokud by byl překreslen. Netýká se to jen CSS pravidel, jejichž hodnoty se změnily.
Můžete použít jak CSS názvy vlastností s pomlčkami (jako background-color
), tak DOM názvy vlastností style
s camel case (jako backgroundColor
). Můžete také definovat CSS vlastní vlastnosti, pokud je váš prohlížeč podporuje.
Mithril.js se nepokouší přidávat jednotky k číselným hodnotám. Jednoduše je převede na řetězec.
Události
Mithril.js podporuje vazbu obslužných rutin událostí pro všechny DOM události, včetně událostí, jejichž specifikace nedefinují vlastnost on${event}
, jako je touchstart
.
function doSomething(e) {
console.log(e);
}
m('div', { onclick: doSomething });
Mithril.js přijímá funkce a objekty EventListener. Takže to bude také fungovat:
var clickListener = {
handleEvent: function (e) {
console.log(e);
},
};
m('div', { onclick: clickListener });
Ve výchozím nastavení, když se spustí událost připojená pomocí hyperscriptu, Mithril.js automaticky provede překreslení po dokončení obslužné funkce události. To platí, pokud používáte m.mount
nebo m.route
místo m.render
přímo. Automatické překreslení můžete vypnout konkrétně pro jednu událost nastavením e.redraw = false
:
m('div', {
onclick: function (e) {
// Zabránit automatickému překreslení
e.redraw = false;
},
});
Vlastnosti
Mithril.js podporuje DOM funkce, které jsou přístupné prostřednictvím vlastností, jako jsou vlastnosti <select>
selectedIndex
a value
.
m('select', { selectedIndex: 0 }, [
m('option', 'Option A'),
m('option', 'Option B'),
]);
Komponenty
Mithril.js vám umožňuje zapouzdřit logiku do jednotky a používat ji, jako by to byl element. Jsou základem pro vytváření velkých, škálovatelných aplikací.
Komponenta je v podstatě jakýkoli JavaScriptový objekt, který má metodu view
. Chcete-li použít komponentu, předejte komponentu jako první argument do m()
místo předávání řetězce CSS selektoru. Můžete předat argumenty komponentě definováním atributů a potomků, jak je znázorněno v příkladu níže.
// definice komponenty
var Greeter = {
view: function (vnode) {
return m('div', vnode.attrs, ['Hello ', vnode.children]);
},
};
// použití komponenty
m(Greeter, { style: 'color:red;' }, 'world');
// Vykreslí do tohoto HTML:
// <div style="color:red;">Hello world</div>
Chcete-li se dozvědět více o komponentách, viz stránka komponent.
Metody životního cyklu
Vnode a komponenty mohou mít metody životního cyklu (říká se jim také hooky). Ty se volají v různých fázích životnosti DOM elementu. Metody životního cyklu podporované Mithril.js jsou: oninit
, oncreate
, onupdate
, onbeforeremove
, onremove
a onbeforeupdate
.
Metody životního cyklu jsou definovány stejným způsobem jako obslužné rutiny DOM událostí, ale místo objektu Event přijímají vnode jako argument:
function initialize(vnode) {
console.log(vnode);
}
m('div', { oninit: initialize });
Hook | Popis |
---|---|
oninit(vnode) | Spustí se před vykreslením vnode do skutečného DOM elementu. |
oncreate(vnode) | Spustí se po připojení vnode k DOM. |
onupdate(vnode) | Spustí se pokaždé, když dojde k překreslení. |
onbeforeremove(vnode) | Spustí se před odebráním DOM elementu z dokumentu. Pokud je vrácen Promise, Mithril.js odpojí DOM element až po dokončení promise. Tato metoda se spustí jen na elementu, který se odpojuje od svého rodiče, ale ne na jeho dětech. |
onremove(vnode) | Spustí se po odebrání DOM elementu z dokumentu. Pokud je definován hook onbeforeremove , onremove je volán po volání done . Tato metoda se spouští na elementu, který je odpojen od svého nadřazeného elementu, a na všech jeho potomcích |
onbeforeupdate(vnode, old) | Spustí se před onupdate , a pokud vrátí false , zabrání rozdílu pro element a všechny jeho potomky |
Chcete-li se dozvědět více o metodách životního cyklu, viz stránka metod životního cyklu.
Klíče
Vnode v seznamu mohou mít speciální atribut nazvaný key
. Ten lze použít ke správě identity DOM elementu, jak se mění data modelu, která generují seznam vnode.
Typicky by key
měl být jedinečný identifikátor objektů v datovém poli.
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));
Použití klíče zajistí, že pokud se pole users promíchá a zobrazení se překreslí, vstupy se promíchají ve stejném pořadí. Tím se zachová správné zaměření a stav DOM.
Chcete-li se dozvědět více o klíčích, viz stránka klíčů.
SVG a MathML
Mithril.js plně podporuje SVG. Xlink je také podporován, ale na rozdíl od verzí Mithril.js před v1.0 musí mít explicitně definovaný jmenný prostor:
m('svg', [m("image[xlink:href='image.gif']")]);
MathML je také plně podporován.
Vytváření dynamických šablon
Vzhledem k tomu, že vnořené vnode jsou prosté výrazy JavaScriptu, můžete jednoduše použít funkce JavaScriptu k manipulaci s nimi.
Dynamický text
var user = { name: 'John' };
m('.name', user.name); // <div class="name">John</div>
Smyčky
Použijte metody Array
, jako je map
k iteraci přes seznamy dat.
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)
// ))
Podmínky
Použijte ternární operátor k podmíněnému nastavení obsahu v zobrazení.
var isError = false;
m('div', isError ? 'An error occurred' : 'Saved'); // <div>Saved</div>
Nemůžete používat příkazy JavaScriptu, jako jsou if
nebo for
ve výrazech JavaScriptu. Je vhodnější se těmto příkazům úplně vyhnout a místo toho používat výše uvedené konstrukce výhradně, aby byla struktura šablon lineární a deklarativní.
Převod HTML
V Mithril.js je dobře formátovaný HTML platný JSX. K integraci nezávisle vytvořeného HTML souboru do projektu pomocí JSX je zapotřebí jen málo úsilí kromě kopírování a vkládání.
Při použití hyperscriptu je nutné převést HTML na syntaxi hyperscriptu před spuštěním kódu. Pro usnadnění toho můžete použít převodník HTML na šablonu Mithril.
Vyhněte se anti-vzorům
Ačkoli je Mithril.js flexibilní, některé vzory kódu se nedoporučují:
Vyhněte se dynamickým selektorům
Různé DOM elementy mají různé atributy a často i různé chování. Pokud uděláte selektor konfigurovatelný, může to vést k tomu, že se detaily implementace komponenty dostanou mimo její rozsah.
// VYVARUJTE SE
var BadInput = {
view: function (vnode) {
return m('div', [m('label'), m(vnode.attrs.type||'input')]);
},
};
Místo vytváření dynamických selektorů se doporučuje explicitně kódovat každou platnou možnost nebo refaktorovat proměnlivou část kódu.
// PREFERUJTE explicitní kód
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')]);
},
};
// PREFERUJTE refaktorování variability
var BetterLabeledComponent = {
view: function (vnode) {
return m('div', [m('label', vnode.attrs.title), vnode.children]);
},
};
Vyhněte se vytváření vnode mimo zobrazení
Když překreslení narazí na vnode, který se striktně rovná vnode v předchozím vykreslení, bude přeskočen a jeho obsah nebude aktualizován. I když se to může jevit jako příležitost pro optimalizaci výkonu, je třeba se tomu vyhnout, protože to zabraňuje dynamickým změnám ve stromu tohoto uzlu - to vede k vedlejším účinkům, jako je selhání spouštění metod životního cyklu po proudu při překreslení. V tomto smyslu jsou Mithril.js vnode neměnné: nové vnode jsou porovnávány se starými; mutace vnode nejsou trvalé.
Dokumentace ke komponentám obsahuje podrobnější informace a příklad tohoto anti-vzoru.