Migrálás v1.x-ről
A v2.x szinte teljesen API-kompatibilis a v1.x-szel, de van néhány kompatibilitástörő változtatás.
Értékadás a vnode.state-hez
A v1.x-ben módosíthattad a vnode.state-et, és bármit hozzárendelhettél. A v2.x-ben ez hibát eredményez. Az átalakítás módja változó lehet, de a legtöbb esetben egyszerűen a vnode.state hivatkozásokat vnode.state.foo-ra kell cserélni, ahol a foo helyett egy megfelelő nevet választasz (például count, ha ez egy számláló aktuális értéke).
v1.x
var Counter = {
oninit: function (vnode) {
vnode.state = 0;
},
view: function (vnode) {
return m('.counter', [
m(
'button',
{
onclick: function () {
vnode.state--;
},
},
'-'
),
vnode.state,
m(
'button',
{
onclick: function () {
vnode.state++;
},
},
'+'
),
]);
},
};v2.x
var Counter = {
oninit: function (vnode) {
vnode.state.count = 0;
},
view: function (vnode) {
return m('.counter', [
m(
'button',
{
onclick: function () {
vnode.state.count--;
},
},
'-'
),
vnode.state.count,
m(
'button',
{
onclick: function () {
vnode.state.count++;
},
},
'+'
),
]);
},
};Amikor a v1.0 megjelent, nem voltak osztály- és closure komponensek, így csak azt vette ki, amire szüksége volt a vnode.tag-ből. Ez az implementációs részlet tette lehetővé, hogy néhányan el is kezdjék használni. A dokumentáció is utalt arra, hogy ez lehetséges. Most a dolgok másképp vannak, és ez megkönnyíti a kezelést implementációs szempontból, mivel csak egy hivatkozás van az állapotra (state), nem kettő.
Útvonal-horgonyok változásai
A v1.x-ben az oncreate: m.route.link és (ha a link megváltozhatott) az onupdate: m.route.link életciklus hook-okat használtad a vnode-on, ami útvonalváltoztatást indított. A v2.x-ben most egy m.route.Link komponenst kell használnod. A szelektor egy selector: attribútumban adható meg, ha az m("a", ...)-tól eltérő elemet használtál. Az opciók az options:-on keresztül adhatók meg, a disabled attribútummal letilthatod, és más attribútumok is megadhatók inline, beleértve a href:-et (kötelező). A selector: bármilyen szelektor lehet, amely érvényes az m első argumentumaként, és a [href=...] és [disabled] attribútumok megadhatók a szelektornál, valamint a normál opcióknál is.
v1.x
m('a', {
href: '/path',
oncreate: m.route.link,
});
m('button', {
href: '/path',
oncreate: m.route.link,
});
m('button.btn[href=/path]', {
oncreate: m.route.link,
});v2.x
m(m.route.Link, {
href: '/path',
});
m(m.route.Link, {
selector: 'button',
href: '/path',
});
m(m.route.Link, {
selector: 'button.btn[href=/path]',
});Az m.request hibakezelésének változásai
A v1.x-ben az m.request feldolgozta a JSON hívások hibáit, és az eredményül kapott objektum tulajdonságait a válaszobjektumhoz rendelte. Tehát, ha egy 403-as státuszú választ kaptál, és a választörzse {"code": "backoff", "timeout": 1000} volt, akkor a hibának két extra tulajdonsága lett volna: err.code = "backoff" és err.timeout = 1000.
A v2.x-ben a válasz az response tulajdonságba kerül az eredményen, és egy code tulajdonság tartalmazza az eredményül kapott státuszkódot. Tehát, ha egy 403-as státuszú választ kaptál, és a választörzse {"code": "backoff", "timeout": 1000} volt, akkor a hibához két tulajdonság lenne hozzárendelve: err.response = {code: "backoff", timeout: 1000} és err.code = 403.
m.withAttr eltávolításra került
A v1.x-ben az eseményfigyelők használhatták az oninput: m.withAttr("value", func)-ot és hasonlót. A v2.x-ben egyszerűen olvasd ki az értékeket közvetlenül az esemény célpontjából (event's target). Jól működött együtt a streamekkel, de mivel az m.withAttr("value", stream) módszer közel sem volt olyan gyakori, mint az m.withAttr("value", prop), az m.withAttr elvesztette hasznosságának nagy részét, ezért eltávolították.
v1.x
var value = '';
// In your view
m('input[type=text]', {
value: value(),
oninput: m.withAttr('value', function (v) {
value = v;
}),
});
// OR
var value = m.stream('');
// In your view
m('input[type=text]', {
value: value(),
oninput: m.withAttr('value', value),
});v2.x
var value = '';
// In your view
m('input[type=text]', {
value: value,
oninput: function (ev) {
value = ev.target.value;
},
});
// OR
var value = m.stream('');
// In your view
m('input[type=text]', {
value: value(),
oninput: function (ev) {
value(ev.target.value);
},
});m.route.prefix
A v1.x-ben az m.route.prefix egy függvény volt, amelyet az m.route.prefix(prefix)-en keresztül hívtak meg. Most egy tulajdonság, amelyet az m.route.prefix = prefix segítségével állítasz be.
v1.x
m.route.prefix('/root');v2.x
m.route.prefix = '/root';m.request/m.jsonp paraméterek és törzs
A data és a useBody átalakult params-szá (az URL-be interpolált és a kéréshez hozzáfűzött lekérdezési paraméterek) és body-vá (az alapul szolgáló XHR-ben elküldendő törzs). Ez sokkal jobb irányítást biztosít a ténylegesen elküldött kérés felett, és lehetővé teszi, hogy lekérdezési paraméterekbe interpolálj POST kérésekkel, és GET kéréseket hozz létre törzsekkel.
Az m.jsonp, mivel nincs értelmes "törzse", csak a params-ot használja, így a data átnevezése params-ra elegendő ehhez a metódushoz.
v1.x
m.request('https://example.com/api/user/:id', {
method: 'GET',
data: { id: user.id },
});
m.request('https://example.com/api/user/create', {
method: 'POST',
data: userData,
});v2.x
m.request('https://example.com/api/user/:id', {
method: 'GET',
params: { id: user.id },
});
m.request('https://example.com/api/user/create', {
method: 'POST',
body: userData,
});Útvonal sablonok
A v1.x-ben három különálló útvonal sablon szintaxis létezett, amelyek bár hasonlóak voltak, 2 külön tervezett szintaxissal és 3 különböző implementációval rendelkeztek. Elég ad-hoc módon lett definiálva, és a paraméterek általában nem voltak escape-elve. Most minden kódolva van, ha :key szerepel a mintában, és nyers (nem kódolt), ha :key... szerepel. Ha a dolgok váratlanul kódolva vannak, használd a :path...-ot. Ennyire egyszerű.
Konkrétan, itt van, hogy ez hogyan érinti az egyes metódusokat:
m.request és m.jsonp URL-ek, m.route.set útvonalak
A v2.x-ben az útvonal komponensek automatikusan escape-elve vannak, amikor interpolálva vannak. Tegyük fel, hogy meghívod az m.route.set("/user/:name/photos/:id", {name: user.name, id: user.id})-et. Korábban, ha a user {name: "a/b", id: "c/d"} volt, akkor ez az útvonalat /user/a%2Fb/photos/c/d-re állította volna, de most /user/a%2Fb/photos/c%2Fd-re állítja. Ha szándékosan akarod egy kulcsot escape nélkül interpolálni, használd helyette a :key...-ot.
A v2.x-ben a kulcsok nem tartalmazhatnak . vagy - karaktereket. A v1.x-ben bármit tartalmazhattak a /-on kívül.
Az inline lekérdezési stringekben, mint például az /api/search?q=:query, az interpolációk nem történnek meg a v2.x-ben. Add át ezeket a params-on keresztül a megfelelő kulcsnevekkel, anélkül, hogy megadná a lekérdezési stringben.
m.route útvonal minták
A :key... formájú útvonal kulcsok a v1.x-ben URL dekódolva tértek vissza, de a v2.x-ben a nyers URL-t adják vissza.
Korábban az olyan dolgok, mint a :key.md tévesen elfogadásra kerültek, és az eredményül kapott paraméter értéke keymd: "..." lett. Ez már nem így van - a .md most a minta része, nem a név.
Lifecycle hívási sorrend
A v1.x-ben a komponens vnode-jain beállított attribútumokhoz tartozó lifecycle hook-ok minden esetben a komponens saját lifecycle hook-jai előtt futottak le. A v2.x-ben ez csak az onbeforeupdate lifecycle hook esetében igaz. Tehát előfordulhat, hogy ennek megfelelően kell módosítanod a kódot.
v1.x
var Comp = {
oncreate: function () {
console.log('Component oncreate');
},
view: function () {
return m('div');
},
};
m.mount(document.body, {
view: function () {
return m(Comp, {
oncreate: function () {
console.log('Attrs oncreate');
},
});
},
});
// Naplók:
// Attrs oncreate
// Component oncreatev2.x
var Comp = {
oncreate: function () {
console.log('Component oncreate');
},
view: function () {
return m('div');
},
};
m.mount(document.body, {
view: function () {
return m(Comp, {
oncreate: function () {
console.log('Attrs oncreate');
},
});
},
});
// Naplók:
// Component oncreate
// Attrs oncreatem.redraw szinkronitás
Az m.redraw() a v2.x-ben mindig aszinkron. Kifejezetten kérhetsz szinkron újrarajzolást az m.redraw.sync() segítségével, feltéve, hogy jelenleg nem történik újrarajzolás.
Szelektor-attribútumok prioritása
A v1.x-ben a szelektorban megadott attribútumok elsőbbséget élveztek az attribútum objektumban megadott attribútumokkal szemben. Például az m("[a=b]", {a: "c"}).attrs {a: "b"}-t adott vissza.
A v2.x-ben az attribútum objektumban megadott attribútumok elsőbbséget élveznek a szelektor attribútumokkal szemben. Például az m("[a=b]", {a: "c"}).attrs {a: "c"}-t ad vissza.
Ne feledd, hogy ez technikailag visszatérés a v0.2.x viselkedéshez.
Gyermekek normalizálása
A v1.x-ben a komponens vnode-jainak gyermekei ugyanúgy normalizálva lettek, mint a többi vnode. A v2.x-ben ez már nem így van, és ennek megfelelően kell tervezned. Ez nem befolyásolja a rendereléskor végzett normalizálást.
m.request fejlécek
A v1.x-ben a Mithril.js ezt a két fejlécet állította be minden nem-GET kérésnél, de csak akkor, ha a useBody értéke true volt (ami az alapértelmezett), és a többi felsorolt feltétel is teljesült:
Content-Type: application/json; charset=utf-8a JSON törzsű kérésekhezAccept: application/json, text/*a JSON válaszokat váró kérésekhez
A v2.x-ben a Mithril.js az elsőt állítja be minden JSON törzsű kéréshez, amely != null, és alapértelmezés szerint kihagyja, egyébként, és ez független attól, hogy melyik metódust választják, beleértve a GET kéréseket is.
A két fejléc közül az első, a Content-Type, CORS prefetch-et vált ki, mivel nem szerepel a CORS-safelisted request header-ek között a megadott tartalomtípus miatt, és ez új hibákat okozhat attól függően, hogy a CORS hogyan van konfigurálva a szerveren. Ha problémákba ütközöl ezzel, akkor lehet, hogy felül kell írnod a kérdéses fejlécet a headers: {"Content-Type": "text/plain"} átadásával. (Az Accept fejléc nem vált ki semmit, így nem kell felülbírálnod.)
Az egyetlen tartalomtípus, amely lehetővé teszi a Fetch specifikáció számára a CORS prefetch ellenőrzések elkerülését, az az application/x-www-form-urlencoded, a multipart/form-data és a text/plain. Semmi mást nem engedélyez, és szándékosan tiltja a JSON-t.
Lekérdezési paraméterek URL hash részekben az útvonalakban
A v1.x-ben megadhatsz lekérdezési paramétereket az útvonalakhoz mind a lekérdezési stringben, mind a hash stringben, így az m.route.set("/route?foo=1&bar=2"), az m.route.set("/route?foo=1#bar=2") és az m.route.set("/route#foo=1&bar=2") mind egyenértékűek voltak, és az azokból kinyert attribútumok {foo: "1", bar: "2"} lettek volna.
A v2.x-ben a hash stringek tartalma figyelmen kívül marad, de a hash string maga megőrződik. Tehát az egyesekből kinyert attribútumok a következők lennének:
m.route.set("/route?foo=1&bar=2")→{foo: "1", bar: "2"}m.route.set("/route?foo=1#bar=2")→{foo: "1"}m.route.set("/route#foo=1&bar=2")→{}
Ennek az az oka, hogy az olyan URL-ek, mint a https://example.com/#!/route#key technikailag érvénytelenek az URL specifikáció szerint, és még az azt megelőző RFC szerint is érvénytelenek voltak, és csak a HTML specifikáció egy furcsasága, hogy engedélyezettek. (A HTML specifikációnak meg kellett volna követelnie, hogy az azonosítók és a helyfragmentumok a kezdetektől fogva érvényes URL fragmentumok legyenek, ha követni akarta a specifikációt.)
Vagy röviden, ne használj érvénytelen URL-eket!
Kulcsok
A v1.x-ben szabadon keverhetted a kulccsal ellátott és a kulcs nélküli vnode-okat. Ha az első node kulccsal van ellátva, akkor a rendszer kulcsos diff-et hajt végre, feltételezve, hogy minden elemhez tartozik kulcs, és figyelmen kívül hagyja a hiányzó kulcsokat. Ellenkező esetben egy iteratív diff kerül végrehajtásra, és ha egy node-nak van kulcsa, akkor ellenőrizni kell, hogy nem változott-e meg ugyanabban az időben, amikor a tagek és hasonlók ellenőrzésre kerülnek.
A v2.x-ben a fragmentumok és az elemek gyermekeinek listái vagy mind kulccsal ellátottak, vagy mind kulcs nélküliek kell, hogy legyenek. A lyukak is kulcs nélkülieknek minősülnek ezen ellenőrzés céljából - már nem hagyja figyelmen kívül őket.
Ha ki kell kerülnöd, használd egyetlen vnode-ot tartalmazó fragmentum idiómáját, mint például [m("div", {key: whatever})].
m.version eltávolítva
Általában kevés haszna volt, és bármikor visszaadhatod magad. Inkább a funkció detektálást kellene előnyben részesítened annak megállapításához, hogy mely funkciók érhetők el, és a v2.x API-t úgy tervezték, hogy ezt jobban lehetővé tegye.