Zpracování cest
m.route a m.request používají koncept cesty (path). Ta slouží k vytvoření URL adresy, na kterou se aplikace přesměrovává, nebo ze které načítá data.
Typy cest
Existují dva základní typy cest: surové cesty (raw paths) a parametrizované cesty (parameterized paths).
- Surové cesty jsou prosté řetězce, které se používají přímo jako URL adresy. Neprovádí se žádná substituce ani rozdělování. Pouze se normalizují a na konec se připojí parametry.
- Parametrizované cesty umožňují vkládat hodnoty do URL adres, které jsou automaticky escapovány pro větší pohodlí a ochranu proti URL injekci.
Pro funkci m.request to mohou být prakticky jakékoli URL adresy, ale pro routes pouze absolutní názvy cest URL bez schémat a domén.
Parametry cesty
Parametry cesty jsou samy o sobě poměrně jednoduché. Vyskytují se ve dvou formách:
:foo- Toto vloží hodnotuparams.foodo URL, přičemž ji nejprve escapuje.:foo...- Toto vloží surovou cestuparams.foodo URL bez escapování.
Možná se ptáte, co objekt params představuje. Je to jednoduše objekt params buď v m.route.set(path, params), nebo v m.request({url, params}).
Při definování rout pomocí m.route(root, defaultRoute, routes) můžete tyto parametry použít k extrahování hodnot z URL. Fungují v podstatě stejně jako při vytváření cest, pouze v opačném směru.
// Upravit jednu položku
m.route(document.body, '/edit/1', {
'/edit/:id': {
view: function () {
return [m(Menu), m('h1', 'Editing user ' + m.route.param('id'))];
},
},
});
// Upravit položku podle cesty
m.route(document.body, '/edit/pictures/image.jpg', {
'/edit/:file...': {
view: function () {
return [m(Menu), m('h1', 'Editing file ' + m.route.param('file'))];
},
},
});V prvním příkladu, pokud přejdete na výchozí routu, m.route.param("id") by vracelo "1" a v druhém příkladu m.route.param("file") by vracelo pictures/image.jpg.
Parametry cesty mohou být odděleny znaky /, - nebo .. To umožňuje vytvářet dynamické segmenty cesty a poskytuje větší flexibilitu než pouhý název cesty. Například byste mohli porovnávat routy jako "/edit/:name.:ext" pro úpravy na základě přípony souboru nebo "/:lang-:region/view" pro lokalizovanou routu.
Parametry cesty fungují stylem "greedy": pokud máme deklarovanou routu "/edit/:name.:ext" a přejdeme na /edit/file.test.png, extrahované parametry budou {name: "file.test", ext: "png"}, a ne {name: "file", ext: "test.png"}. Stejně tak, pokud máme "/route/:path.../view/:child..." a přejdeme na /route/foo/view/bar/view/baz, extrahované parametry budou {path: "foo/view/bar", child: "baz"}.
Normalizace parametrů
Parametry cesty, které jsou vloženy do URL, se automaticky odstraňují z řetězce dotazu (query string), aby se zjednodušila a zachovala čitelnost URL. Například následující kód odešle serverový požadavek GET /api/user/1/connections?sort=name-asc, přičemž vynechá duplicitní id=1 v URL.
m.request({
url: 'https://example.com/api/user/:userID/connections',
params: {
userID: 1,
sort: 'name-asc',
},
});Můžete také explicitně zadat parametry přímo v řetězci dotazu, například takto, což je ekvivalentní výše uvedenému:
m.request({
url: 'https://example.com/api/user/:userID/connections?sort=name-asc',
params: {
userID: 1,
},
});Samozřejmě můžete obojí kombinovat. Následující kód odešle požadavek na GET /api/user/1/connections?sort=name-asc&first=10.
m.request({
url: 'https://example.com/api/user/:userID/connections?sort=name-asc',
params: {
userID: 1,
first: 10,
},
});Tato vlastnost se vztahuje i na porovnávání tras: můžete porovnávat routu s explicitními parametry v řetězci dotazu. Odpovídající parametr se zachová pro snadný přístup, takže k němu můžete přistupovat přes parametry vnode nebo pomocí m.route.param. Ačkoli je to možné, obecně se to nedoporučuje. Pro definici stránek byste měli upřednostňovat cesty. Může to být užitečné, pokud potřebujete vygenerovat mírně odlišné zobrazení pro specifický typ souboru, ale z logického hlediska se jedná o parametr dotazu, a ne o samostatnou stránku.
// Poznámka: toto se obecně *nedoporučuje* - měli byste upřednostňovat cesty pro deklarace rout,
// nikoli řetězce dotazu.
m.route(document.body, '/edit/1', {
'/edit?type=image': {
view: function () {
return [m(Menu), m('h1', 'Editing photo')]; // Úprava fotografie
},
},
'/edit': {
view: function () {
return [m(Menu), m('h1', 'Editing ' + m.route.param('type'))]; // Úprava typu
},
},
});Parametry dotazu se implicitně přijímají - nemusíte je explicitně definovat, abyste je mohli použít. Můžete porovnávat na základě existující hodnoty, jako v "/edit?type=image", ale nemusíte používat "/edit?type=:type" k přijetí hodnoty. Ve skutečnosti by Mithril.js s tím zacházel, jako byste se pokoušeli doslova porovnat s m.route.param("type") === ":type", což pravděpodobně nechcete. Jednoduše řečeno, použijte m.route.param("key") nebo atributy komponenty tras ke čtení parametrů dotazu.
Normalizace cesty
Analyzované cesty jsou vždy vraceny s odstraněnými duplicitními parametry a nadbytečnými lomítky a vždy začínají lomítkem. Tyto drobné rozdíly mohou komplikovat routing a zpracování cest. Mithril.js interně normalizuje cesty pro routing, ale přímo nezpřístupňuje aktuální, normalizovanou routu. (Můžete ji vypočítat pomocí m.parsePathname(m.route.get()).path.)
Když jsou parametry během porovnávání deduplikovány, parametry v řetězci dotazu mají přednost před parametry v názvu cesty a parametry směrem ke konci URL mají přednost před parametry blíže k začátku URL.
Escapování cesty
Existují některé znaky, které, pokud je chcete použít doslova, musíte escapovat. Funkce encodeURIComponent tyto znaky (a další) kóduje. Při substituci parametrů a přidávání parametrů dotazu se automaticky použije toto kódování. Zde jsou ty, které Mithril.js interpretuje:
:=%3A/=%2F(vyžadováno pouze v cestách)%=%25?=%3F(vyžadováno pouze v cestách)#=%23
Samozřejmě, existují i další znaky, které musíte escapovat podle specifikace URL, jako jsou mezery. Ale jak již bylo uvedeno, encodeURIComponent to dělá za vás a Mithril.js to implicitně používá, když substituujete parametry. Starat se o to musíte pouze v případě, že explicitně zadáváte parametry, například v m.request("https://example.com/api/user/User%20Name/:field", {params: {field: ...}}).