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 oncreate
v2.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 oncreate
m.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-8
a 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.