Skip to content
Mithril.js 2
Main Navigation NávodAPI

čeština

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
magyar

čeština

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
magyar

Vzhled

Sidebar Navigation

API

Základní API

m(selector, attributes, children)

render(element, vnodes)

mount(root, component)

route(root, defaultRoute, routes)

request(options)

parseQueryString(string)

buildQueryString(object)

buildPathname(object)

parsePathname(string)

Trust(html)

fragment(attrs, children)

redraw()

censor(object, extra)

Volitelné API

stream()

Návod

Na této stránce

route(root, defaultRoute, routes) ​

Popis ​

Zajišťuje navigaci mezi stránkami v aplikaci.

javascript
var Home = {
  view: function () {
    return 'Welcome';
  },
};

m.route(document.body, '/home', {
  '/home': Home, // definuje `https://localhost/#!/home`
});

V aplikaci smí být pouze jedno volání m.route.

Signatura ​

m.route(root, defaultRoute, routes)

ArgumentTypeRequiredDescription
rootElementAnoDOM element, který bude rodičovským uzlem pro vykreslovaný podstrom.
defaultRouteStringAnoCesta, na kterou se má přesměrovat, pokud aktuální URL neodpovídá žádné definované cestě. Poznámka: Toto není počáteční cesta aplikace. Počáteční cesta je URL v adresním řádku prohlížeče.
routesObject<String,Component|RouteResolver>AnoObjekt, jehož klíče jsou cesty a hodnoty jsou buď komponenty, nebo RouteResolver.
returnsVrací undefined.

Jak číst signatury

Statické členy ​

m.route.set ​

Přesměruje na odpovídající cestu, nebo na výchozí cestu, pokud nelze najít žádnou odpovídající cestu. Spustí asynchronní překreslení všech připojených komponent.

m.route.set(path, params, options)

ArgumentTypeRequiredDescription
pathStringAnoNázev cesty, na kterou se má přesměrovat, bez předpony. Cesta může obsahovat parametry, které budou interpolovány s hodnotami z params.
paramsObjectNeParametry směrování. Pokud path obsahuje zástupné symboly pro parametry, vlastnosti tohoto objektu se interpolují do řetězce cesty.
options.replaceBooleanNeUrčuje, zda se má vytvořit nový záznam v historii prohlížeče, nebo nahradit aktuální. Výchozí hodnota je false.
options.stateObjectNeObjekt state, který se má předat podkladovému volání history.pushState / history.replaceState. Tento objekt stavu je k dispozici ve vlastnosti history.state a je sloučen do objektu parametrů směrování. Upozorňujeme, že tato možnost funguje pouze při použití rozhraní API pushState, ale je ignorována, pokud prohlížeč toto API nepodporuje.
options.titleStringNeŘetězec title, který se má předat podkladovému volání history.pushState / history.replaceState.
returnsVrací undefined.

Pamatujte, že při použití .set s params musíte také definovat cestu s parametry:

javascript
var Article = {
  view: function (vnode) {
    return 'This is article ' + vnode.attrs.articleid;
  },
};

m.route(document.body, {
  '/article/:articleid': Article,
});
m.route.set('/article/:articleid', { articleid: 1 });

m.route.get ​

Vrací poslední plně vyřešenou cestu směrování, bez předpony. Může se lišit od cesty zobrazené v adresním řádku, dokud asynchronní cesta čeká na vyřešení.

path = m.route.get()

ArgumentTypeRequiredDescription
returnsStringVrací poslední plně vyřešenou cestu.

m.route.prefix ​

Definuje předponu směrovače. Předpona směrovače je fragment URL, který určuje podkladovou strategii používanou směrovačem.

m.route.prefix = prefix

ArgumentTypeRequiredDescription
prefixStringAnoPředpona, která řídí podkladovou strategii směrování používanou Mithril.js.

Toto je jednoduchá vlastnost, takže ji můžete číst i zapisovat.

m.route.Link ​

Tato komponenta vytváří dynamický směrovaný odkaz. Jejím účelem je vytvářet odkazy <a> s lokálními href, které jsou transformovány tak, aby správně fungovaly s předponou cesty.

javascript
m(m.route.Link, { href: '/foo' }, 'foo');

// Pokud se m.route.prefix nezměnila z výchozí strategie, vykreslí se:
// <a href="#!/foo">foo</a>

Odkazy akceptují následující speciální atributy:

  • selector je to, co by se předalo jako první argument do m: platný je jakýkoli selektor, včetně prvků, které nejsou <a>.
  • params & options jsou argumenty se stejnými názvy, jaké jsou definovány v m.route.set.
  • disabled, pokud je true, zakáže chování směrování a jakýkoli vázaný obslužný program onclick a připojí atribut data-disabled="true" pro usnadnění přístupu; pokud je prvek <a>, href se odebere.

Chování směrování nelze zabránit pomocí standardních obslužných funkcí událostí: použijte místo toho disabled.

javascript
m(
  m.route.Link,
  {
    href: '/foo',
    selector: 'button.large',
    disabled: true,
    params: { key: 'value' },
    options: { replace: true },
  },
  'link name'
);

// Vykreslí se:
// <button disabled aria-disabled="true" class="large">link name</button>

vnode = m(m.route.Link, attributes, children)

ArgumentTypeRequiredDescription
attributes.hrefObjectAnoCílová cesta, na kterou se má navigovat.
attributes.disabledBooleanNeZnemožní interakci s prvkem.
attributes.selectorString|Object|FunctionNeSelektor pro m, výchozí hodnota je "a".
attributes.optionsObjectNeNastaví options předané do m.route.set.
attributes.paramsObjectNeNastaví params předané do m.route.set.
attributesObjectNeJakékoli další atributy, které mají být předány do m.
childrenArray<Vnode>|String|Number|BooleanNePodřízené vnode pro tento odkaz.
returnsVnodeVnode.

m.route.param ​

Načte parametr cesty z aktuální cesty. Parametr cesty je pár klíč-hodnota. Parametry cesty mohou pocházet z několika různých zdrojů:

  • interpolace cest (např. pokud je cesta /users/:id a vyřeší se na /users/1, parametr cesty má klíč id a hodnotu "1")
  • řetězce dotazů (např. pokud je cesta /users?page=1, parametr cesty má klíč page a hodnotu "1")
  • history.state (např. pokud je history.state {foo: "bar"}, parametr cesty má klíč foo a hodnotu "bar")

value = m.route.param(key)

ArgumentTypeRequiredDescription
keyStringNeNázev parametru cesty (např. id v cestě /users/:id nebo page v cestě /users/1?page=3 nebo klíč v history.state).
returnsString|ObjectVrací hodnotu pro zadaný klíč. Pokud není zadán klíč, vrátí objekt, který obsahuje všechny klíče interpolace.

Všimněte si, že ve funkci onmatch RouteResolveru nebyla nová cesta ještě plně vyřešena a m.route.param() vrátí parametry předchozí cesty, pokud existují. onmatch obdrží parametry nové cesty jako argument.

m.route.SKIP ​

Speciální hodnota, kterou lze vrátit z funkce onmatch řešiče cest pro přeskočení na další cestu.

RouteResolver ​

RouteResolver je objekt, který neslouží jako komponenta a obsahuje metodu onmatch a/nebo metodu render. Obě metody jsou volitelné, ale musí být přítomna alespoň jedna.

Pokud lze objekt detekovat jako komponentu (přítomností metody view nebo tím, že je function/class), bude s ním zacházeno jako s komponentou, i když má metody onmatch nebo render. Protože RouteResolver není komponenta, nemá metody životního cyklu.

Obecně platí, že RouteResolvers by měly být ve stejném souboru jako volání m.route, zatímco definice komponent by měly být ve svých vlastních modulech.

routeResolver = {onmatch, render}

Při použití komponent si je můžete představit jako speciální syntaxi pro tento řešič cest, za předpokladu, že vaše komponenta je Home:

javascript
var routeResolver = {
  onmatch: function () {
    return Home;
  },
  render: function (vnode) {
    return [vnode];
  },
};

routeResolver.onmatch ​

Hook onmatch se volá, když směrovač potřebuje vybrat komponentu, která se má vykreslit. Volá se jednou při každé změně cesty, ale ne při následných překresleních. Lze jej použít ke spuštění logiky před inicializací komponenty (například logika ověřování, předběžné načítání dat, sledování analytiky přesměrování atd.).

Tato metoda také umožňuje asynchronně definovat, která komponenta bude vykreslena, takže je vhodná pro rozdělení kódu a asynchronní načítání modulů. Chcete-li vykreslit komponentu asynchronně, vraťte Promise, který se vyřeší na komponentu.

Další informace o onmatch naleznete v části rozšířené řešení komponent.

routeResolver.onmatch(args, requestedPath, route)

ArgumentTypeDescription
argsObjectParametry směrování.
requestedPathStringCesta směrovače požadovaná poslední akcí směrování, včetně interpolovaných hodnot parametrů směrování, ale bez předpony. Když je volána funkce onmatch, řešení pro tuto cestu není dokončeno a m.route.get() stále vrací předchozí cestu.
routeStringCesta směrovače požadovaná poslední akcí směrování, s vyloučením interpolovaných hodnot parametrů směrování.
returnsComponent|\Promise<Component>|undefinedVrací komponentu nebo Promise, který se vyřeší na komponentu.

Pokud onmatch vrátí komponentu nebo Promise, který se vyřeší na komponentu, použije se tato komponenta jako vnode.tag pro první argument v metodě render RouteResolveru. V opačném případě je vnode.tag nastaven na "div". Podobně, pokud je metoda onmatch vynechána, vnode.tag je také "div".

Pokud onmatch vrátí Promise, který je odmítnut, směrovač se přesměruje zpět na defaultRoute. Toto chování můžete přepsat voláním .catch na řetězci Promise před jeho vrácením.

routeResolver.render ​

Metoda render se volá při každém překreslení pro odpovídající cestu. Je podobná metodě view v komponentách a existuje pro zjednodušení skládání komponent. Umožňuje vám také uniknout z normálního chování Mithril.js, které nahrazuje celý podstrom.

vnode = routeResolver.render(vnode)

ArgumentTypeDescription
vnodeObjectVnode, jehož objekt atributů obsahuje parametry směrování. Pokud onmatch nevrátí komponentu nebo Promise, který se vyřeší na komponentu, pole tag vnode má výchozí hodnotu "div".
vnode.attrsObjectMapa hodnot parametrů URL.
returnsArray<Vnode>|VnodeVnodes, které mají být vykresleny.

Parametr vnode je pouze m(Component, m.route.param()), kde Component je vyřešená komponenta pro cestu (po routeResolver.onmatch) a m.route.param() je popsáno zde. Pokud tuto metodu vynecháte, výchozí návratová hodnota je [vnode], zabalená ve fragmentu, abyste mohli použít klíčové parametry. V kombinaci s parametrem :key se stane jednoelementovým fragmentem s klíčem, protože nakonec vykreslí něco jako [m(Component, {key: m.route.param("key"), ...})].

Jak to funguje ​

Směrování je systém, který umožňuje vytvářet Single Page Applications (SPA), tj. aplikace, které mohou přecházet z jedné stránky na druhou, aniž by došlo k úplnému obnovení stránky v prohlížeči.

Umožňuje bezproblémovou navigaci při zachování možnosti přidat každou stránku jednotlivě do záložek a možnosti navigovat v aplikaci prostřednictvím mechanismu historie prohlížeče.

Směrování bez obnovení stránky je částečně umožněno rozhraním API history.pushState. Pomocí tohoto rozhraní API je možné programově změnit URL zobrazenou prohlížečem po načtení stránky, ale je odpovědností vývojáře aplikace zajistit, aby navigace na danou URL ze studeného stavu (např. nová karta) vykreslila příslušné značky.

Strategie směrování ​

Strategie směrování určuje, jak knihovna implementuje směrování. Existují tři obecné strategie, které lze použít k implementaci systému směrování SPA, a každá má svá omezení:

  • m.route.prefix = '#!' (výchozí) – Použití identifikátoru fragmentu (aka hash) části URL. URL používající tuto strategii obvykle vypadá takto: https://localhost/#!/page1.
  • m.route.prefix = '?' – Použití řetězce dotazu. URL používající tuto strategii obvykle vypadá takto: https://localhost/?/page1.
  • m.route.prefix = '' – Použití názvu cesty. URL používající tuto strategii obvykle vypadá takto: https://localhost/page1.

Použití strategie hash zaručeně funguje v prohlížečích, které nepodporují history.pushState, protože může použít onhashchange jako náhradu. Použijte tuto strategii, pokud chcete zachovat hashe čistě lokální.

Strategie řetězce dotazu umožňuje detekci na straně serveru, ale nezobrazuje se jako normální cesta. Použijte tuto strategii, pokud chcete podporovat a potenciálně detekovat ukotvené odkazy na straně serveru a nemůžete provést změny nezbytné pro podporu strategie názvu cesty (například pokud používáte Apache a nemůžete upravit svůj .htaccess).

Strategie názvu cesty vytváří nejčistší URL, ale vyžaduje nastavení serveru tak, aby obsluhoval kód aplikace pro jednu stránku z každé URL, na kterou může aplikace směrovat. Použijte tuto strategii, pokud chcete čistší URL.

Aplikace pro jednu stránku, které používají strategii hash, často používají konvenci mít vykřičník za hashem, aby naznačily, že používají hash jako mechanismus směrování, a ne pro účely odkazování na kotvy. Řetězec #! je známý jako hashbang.

Výchozí strategie používá hashbang.

Typické použití ​

Obvykle musíte vytvořit několik komponent pro definování jednotlivých stránek:

javascript
var Home = {
  view: function () {
    return [m(Menu), m('h1', 'Home')];
  },
};

var Page1 = {
  view: function () {
    return [m(Menu), m('h1', 'Page 1')];
  },
};

Ve výše uvedeném příkladu existují dvě komponenty: Home a Page1. Každá obsahuje menu a nějaký text. Menu je samo o sobě definováno jako komponenta, aby se zabránilo opakování:

javascript
var Menu = {
  view: function () {
    return m('nav', [
      m(m.route.Link, { href: '/' }, 'Home'),
      m(m.route.Link, { href: '/page1' }, 'Page 1'),
    ]);
  },
};

Nyní můžeme definovat cesty a mapovat na ně naše komponenty:

javascript
m.route(document.body, '/', {
  '/': Home,
  '/page1': Page1,
});

Zde specifikujeme dvě cesty: / a /page1, které vykreslují své příslušné komponenty, když uživatel přejde na každou URL.

Navigace na různé cesty ​

Ve výše uvedeném příkladu má komponenta Menu dva m.route.Links. To vytvoří prvek, ve výchozím nastavení <a>, a nastaví jej tak, že pokud na něj uživatel klikne, sám přejde na jinou cestu. Neprovádí plnohodnotnou navigaci, pouze lokální změnu v aplikaci.

Můžete také navigovat programově pomocí m.route.set(route). Například m.route.set("/page1").

Při navigaci mezi cestami je předpona směrovače zpracována za vás. Jinými slovy, vynechte hashbang #! (nebo jakoukoli předponu, kterou jste nastavili m.route.prefix na) při propojování cest Mithril.js, a to jak v m.route.set, tak v m.route.Link.

Všimněte si, že při navigaci mezi komponentami je nahrazen celý podstrom. Použijte řešič cest s metodou render, pokud chcete pouze aktualizovat podstrom.

Parametry směrování ​

Někdy chceme mít v cestě ID nebo jiná data, která se mění, ale nechceme explicitně specifikovat samostatnou cestu pro každé možné ID. Abychom toho dosáhli, Mithril.js podporuje parametrizované cesty:

javascript
var Edit = {
  view: function (vnode) {
    return [m(Menu), m('h1', 'Editing ' + vnode.attrs.id)];
  },
};
m.route(document.body, '/edit/1', {
  '/edit/:id': Edit,
});

Ve výše uvedeném příkladu jsme definovali cestu /edit/:id. To vytvoří dynamickou cestu, která odpovídá jakékoli URL, která začíná /edit/ a následují ji nějaká data (např. /edit/1, edit/234 atd.). Hodnota id je pak přístupná jako atribut vnode komponenty (vnode.attrs.id).

Je možné mít v cestě více argumentů, například /edit/:projectID/:userID by vytvořilo vlastnosti projectID a userID v objektu atributů vnode komponenty.

Klíčový parametr ​

Když uživatel přejde z parametrizované cesty na stejnou cestu s jiným parametrem (např. přechod z /page/1 na /page/2 vzhledem k cestě /page/:id), komponenta by nebyla znovu vytvořena od začátku, protože obě cesty se vyřeší na stejnou komponentu, a proto by vedly k virtuálnímu dom diff na místě. To způsobí spuštění hooku onupdate místo oninit/oncreate. Je však poměrně běžné, že vývojář chce synchronizovat opětovné vytvoření komponenty s událostí změny cesty.

Abychom toho dosáhli, je možné kombinovat parametrizaci cesty s klíči pro velmi pohodlný vzor:

javascript
m.route(document.body, '/edit/1', {
  '/edit/:key': Edit,
});

To znamená, že vnode, který je vytvořen pro kořenovou komponentu cesty, má objekt parametru cesty key. Parametry cesty se stanou attrs ve vnode. Když tedy skočíte z jedné stránky na druhou, key se změní a způsobí, že se komponenta znovu vytvoří od začátku (protože klíč říká enginu virtuálního dom, že staré a nové komponenty jsou různé entity).

Můžete tuto myšlenku posunout dále a vytvořit komponenty, které se znovu vytvoří při opětovném načtení:

m.route.set(m.route.get(), {key: Date.now()})

Nebo dokonce použít funkci history state k dosažení znovu načitatelných komponent bez znečištění URL:

m.route.set(m.route.get(), null, {state: {key: Date.now()}})

Všimněte si, že klíčový parametr funguje pouze pro cesty komponent. Pokud používáte řešič cest, budete muset použít jednoelementový fragment s klíčem a předat key: m.route.param("key"), abyste dosáhli stejného výsledku.

Variadické cesty ​

Je také možné mít variadické cesty, tj. cestu s argumentem, který obsahuje URL s lomítky:

javascript
m.route(document.body, '/edit/pictures/image.jpg', {
  '/edit/:file...': Edit,
});

Zpracování chyb 404 ​

Pro izomorfní / univerzální aplikaci JavaScript je kombinace parametru URL a variadické cesty velmi užitečná pro zobrazení vlastní chybové stránky.

V případě chyby 404 Nenalezeno server odešle zpět vlastní chybovou stránku. Když je načten Mithril.js, přesměruje klienta na výchozí cestu, protože nemůže vědět, že cesta.

javascript
m.route(document.body, '/', {
  '/': homeComponent,
  // [...]
  '/:404...': errorPageComponent,
});

Stav historie ​

Je možné plně využít podkladové rozhraní API history.pushState ke zlepšení uživatelského prostředí při navigaci. Například aplikace by si mohla "zapamatovat" stav velkého formuláře, když uživatel opustí stránku navigací pryč, takže pokud by uživatel stiskl tlačítko zpět v prohlížeči, měl by vyplněný formulář spíše než prázdný formulář.

Pro příklad, můžete vytvořit formulář takto:

javascript
var state = {
  term: '',
  search: function () {
    // save the state for this route
    // this is equivalent to `history.replaceState({term: state.term}, null, location.href)`
    m.route.set(m.route.get(), null, {
      replace: true,
      state: { term: state.term },
    });

    // navigate away
    location.href = 'https://google.com/?q=' + state.term;
  },
};

var Form = {
  oninit: function (vnode) {
    state.term = vnode.attrs.term || ''; // populated from the `history.state` property if the user presses the back button
  },
  view: function () {
    return m('form', [
      m("input[placeholder='Search']", {
        oninput: function (e) {
          state.term = e.target.value;
        },
        value: state.term,
      }),
      m('button', { onclick: state.search }, 'Search'),
    ]);
  },
};

m.route(document.body, '/', {
  '/': Form,
});

Tímto způsobem, pokud uživatel vyhledá a stiskne tlačítko zpět pro návrat do aplikace, bude vstup stále vyplněn hledaným výrazem. Tato technika může zlepšit uživatelský zážitek z velkých formulářů a dalších aplikací, kde je neperzistentní stav pro uživatele pracný.

Změna předpony směrovače ​

Předpona směrovače je fragment URL, který určuje podkladovou strategii používanou směrovačem.

javascript
// nastavit na strategii názvu cesty
m.route.prefix = '';

// nastavit na strategii řetězce dotazu
m.route.prefix = '?';

// nastavit na hash bez bang
m.route.prefix = '#';

// nastavit na strategii názvu cesty na URL, která není kořenová
// např. pokud aplikace žije pod `https://localhost/my-app`
m.route.prefix = '/my-app';

Pokročilé rozlišení komponent ​

Místo přímého mapování komponenty na cestu můžete použít objekt RouteResolver. Objekt RouteResolver obsahuje metody onmatch() a/nebo render(). Obě metody jsou volitelné, ale alespoň jedna z nich musí být definována.

javascript
m.route(document.body, '/', {
  '/': {
    onmatch: function (args, requestedPath, route) {
      return Home;
    },
    render: function (vnode) {
      return vnode; // ekvivalentní m(Home)
    },
  },
});

RouteResolver je užitečný pro implementaci pokročilejších scénářů směrování.

Zabalení layoutové komponenty ​

Často je potřeba zabalit všechny nebo většinu směrovaných komponent do opakovaně použitelného obalu (často nazývaného "rozvržení"). K tomu je nutné nejprve vytvořit komponentu, která obsahuje společné prvky, jež budou obalovat různé komponenty:

javascript
var Layout = {
  view: function (vnode) {
    return m('.layout', vnode.children);
  },
};

V uvedeném příkladu se rozvržení skládá pouze z <div> s třídou "layout", která obsahuje potomky předané komponentě. V reálném scénáři může být rozvržení libovolně složité.

Jedním ze způsobů, jak zabalit rozvržení, je definovat anonymní komponentu přímo v mapě cest:

javascript
// příklad 1
m.route(document.body, '/', {
  '/': {
    view: function () {
      return m(Layout, m(Home));
    },
  },
  '/form': {
    view: function () {
      return m(Layout, m(Form));
    },
  },
});

Všimněte si, že komponenta nejvyšší úrovně je anonymní. Při přechodu z cesty / na cestu /form (nebo naopak) se anonymní komponenta zruší a DOM se znovu vytvoří od začátku. Pokud má komponenta Layout definované metody životního cyklu, háčky oninit a oncreate se spustí při každé změně cesty. V závislosti na aplikaci to může být žádoucí, nebo ne.

Pokud chcete, aby byla komponenta Layout porovnávána a udržována v původním stavu, namísto opětovného vytváření od začátku, použijte místo toho RouteResolver jako kořenový objekt:

javascript
// příklad 2
m.route(document.body, '/', {
  '/': {
    render: function () {
      return m(Layout, m(Home));
    },
  },
  '/form': {
    render: function () {
      return m(Layout, m(Form));
    },
  },
});

V tomto případě, pokud má komponenta Layout metody životního cyklu oninit a oncreate, spustí se pouze při první změně cesty (za předpokladu, že všechny cesty používají stejné rozvržení).

Pro objasnění rozdílu mezi oběma příklady je příklad 1 ekvivalentní tomuto kódu:

javascript
// funkčně ekvivalentní příkladu 1
var Anon1 = {
  view: function () {
    return m(Layout, m(Home));
  },
};
var Anon2 = {
  view: function () {
    return m(Layout, m(Form));
  },
};

m.route(document.body, '/', {
  '/': {
    render: function () {
      return m(Anon1);
    },
  },
  '/form': {
    render: function () {
      return m(Anon2);
    },
  },
});

Protože Anon1 a Anon2 jsou odlišné komponenty, jejich podstromy (včetně Layout) jsou znovu vytvořeny od začátku. To se stane i v případě, že jsou komponenty použity přímo bez RouteResolveru.

V příkladu 2, protože Layout je nejvyšší komponenta v obou cestách, DOM pro komponentu Layout je porovnán (tj. ponechán beze změny, pokud nemá žádné změny) a pouze změna z Home na Form spustí opětovné vytvoření této části DOM.

Přesměrování (redirect) ​

Háček onmatch v RouteResolver umožňuje spuštění logiky před inicializací komponenty nejvyšší úrovně dané cesty. Můžete použít buď Mithrilovu funkci m.route.set() nebo nativní HTML API history. Při přesměrování pomocí API history je nutné, aby háček onmatch vrátil Promise, která se nikdy nevyřeší, a tím zabránil vyřešení odpovídající cesty. m.route.set() interně ruší vyřešení odpovídající cesty, takže to není nutné.

Příklad: autentifikace ​

Následující příklad ukazuje, jak vytvořit přihlašovací stěnu, která uživatelům zabrání v zobrazení stránky /secret, pokud se nepřihlásí.

javascript
var isLoggedIn = false;

var Login = {
  view: function () {
    return m('form', [
      m(
        'button[type=button]',
        {
          onclick: function () {
            isLoggedIn = true;
            m.route.set('/secret');
          },
        },
        'Login'
      ),
    ]);
  },
};

m.route(document.body, '/secret', {
  '/secret': {
    onmatch: function () {
      if (!isLoggedIn) m.route.set('/login');
      else return Home;
    },
  },
  '/login': Login,
});

Při načtení aplikace se zavolá onmatch, a protože isLoggedIn je false, aplikace se přesměruje na /login. Po stisknutí tlačítka pro přihlášení se hodnota isLoggedIn změní na true a aplikace se přesměruje na /secret. Háček onmatch se spustí znovu, a protože isLoggedIn je tentokrát true, aplikace vykreslí komponentu Home.

Pro zjednodušení je stav přihlášení uživatele uložen v globální proměnné. Ve výše uvedeném příkladu... a tento příznak se pouze přepne, když uživatel klikne na tlačítko pro přihlášení. Ve skutečné aplikaci by uživatel samozřejmě musel zadat správné přihlašovací údaje a kliknutí na tlačítko pro přihlášení by spustilo požadavek na server pro ověření uživatele:

javascript
var Auth = {
  username: '',
  password: '',

  setUsername: function (value) {
    Auth.username = value;
  },
  setPassword: function (value) {
    Auth.password = value;
  },
  login: function () {
    m.request({
      url: '/api/v1/auth',
      params: { username: Auth.username, password: Auth.password },
    }).then(function (data) {
      localStorage.setItem('auth-token', data.token);
      m.route.set('/secret');
    });
  },
};

var Login = {
  view: function () {
    return m('form', [
      m('input[type=text]', {
        oninput: function (e) {
          Auth.setUsername(e.target.value);
        },
        value: Auth.username,
      }),
      m('input[type=password]', {
        oninput: function (e) {
          Auth.setPassword(e.target.value);
        },
        value: Auth.password,
      }),
      m('button[type=button]', { onclick: Auth.login }, 'Login'),
    ]);
  },
};

m.route(document.body, '/secret', {
  '/secret': {
    onmatch: function () {
      if (!localStorage.getItem('auth-token')) m.route.set('/login');
      else return Home;
    },
  },
  '/login': Login,
});

Přednačítání dat ​

Komponenta obvykle načítá data při inicializaci. Načítání dat tímto způsobem způsobuje, že se komponenta vykreslí dvakrát. První průchod vykreslením nastane při směrování a druhý se spustí po dokončení požadavku. Všimněte si, že loadUsers() vrací promise, ale jakýkoli Promise vrácený oninit je aktuálně ignorován. Druhý průchod vykreslením pochází z možnosti background pro m.request.

javascript
var state = {
  users: [],
  loadUsers: function () {
    return m.request('/api/v1/users').then(function (users) {
      state.users = users;
    });
  },
};

m.route(document.body, '/user/list', {
  '/user/list': {
    oninit: state.loadUsers,
    view: function () {
      return state.users.length > 0
        ? state.users.map(function (user) {
            return m('div', user.id);
          })
        : 'loading';
    },
  },
});

V uvedeném příkladu se při prvním vykreslení uživatelského rozhraní zobrazí "loading", protože state.users je prázdné pole před dokončením požadavku. Jakmile jsou data k dispozici, uživatelské rozhraní se překreslí a zobrazí se seznam ID uživatelů.

RouteResolver lze využít k předběžnému načtení dat před vykreslením komponenty, čímž se předejde blikání uživatelského rozhraní a eliminuje potřeba indikátoru načítání:

javascript
var state = {
  users: [],
  loadUsers: function () {
    return m.request('/api/v1/users').then(function (users) {
      state.users = users;
    });
  },
};

m.route(document.body, '/user/list', {
  '/user/list': {
    onmatch: state.loadUsers,
    render: function () {
      return state.users.map(function (user) {
        return m('div', user.id);
      });
    },
  },
});

render se spustí až po dokončení požadavku, takže ternární operátor je nadbytečný.

Dělení kódu ​

Ve velkých aplikacích může být žádoucí stahovat kód pro každou cestu na vyžádání, spíše než předem. Tento způsob rozdělení kódu je známý jako code-splitting nebo líné načítání. V Mithril.js toho lze dosáhnout vrácením promise z háčku onmatch:

V nejzákladnější podobě by to mohlo vypadat takto:

javascript
// Home.js
module.export = {
  view: function () {
    return [m(Menu), m('h1', 'Home')];
  },
};
javascript
// index.js
function load(file) {
  return m.request({
    method: 'GET',
    url: file,
    extract: function (xhr) {
      return new Function(
        'var module = {};' + xhr.responseText + ';return module.exports;'
      );
    },
  });
}

m.route(document.body, '/', {
  '/': {
    onmatch: function () {
      return load('Home.js');
    },
  },
});

V reálném provozu by však bylo nutné svázat všechny závislosti pro modul Home.js do souboru, který je nakonec obsluhován serverem.

Naštěstí existuje řada nástrojů, které usnadňují svazování modulů pro líné načítání. Zde je příklad použití nativního dynamického import(...), podporovaného mnoha bundlery:

javascript
m.route(document.body, '/', {
  '/': {
    onmatch: function () {
      return import('./Home.js');
    },
  },
});

Typované routy ​

V některých složitějších případech směrování může být žádoucí omezit hodnotu nejen na samotnou cestu, například tak, aby odpovídala pouze číselnému ID. Můžete to snadno provést vrácením m.route.SKIP z cesty.

javascript
m.route(document.body, '/', {
  '/view/:id': {
    onmatch: function (args) {
      if (!/^\d+$/.test(args.id)) return m.route.SKIP;
      return ItemView;
    },
  },
  '/view/:name': UserView,
});

Skryté routy ​

Ve vzácných případech můžete chtít skrýt určité cesty před některými uživateli, ale ne pro všechny. Například uživatel může mít zakázáno zobrazit konkrétního uživatele, a místo zobrazení chyby oprávnění byste raději předstírali, že neexistuje, a přesměrovali na zobrazení 404. V takovém případě můžete použít m.route.SKIP, abyste předstírali, že cesta neexistuje.

javascript
m.route(document.body, '/', {
  '/user/:id': {
    onmatch: function (args) {
      return Model.checkViewable(args.id).then(function (viewable) {
        return viewable ? UserView : m.route.SKIP;
      });
    },
  },
  '/:404...': PageNotFound,
});

Zrušení / blokování cesty ​

RouteResolver onmatch může zabránit vyřešení cesty vrácením promise, která se nikdy nevyřeší. To lze použít k detekci pokusů o nadbytečné vyřešení cesty a jejich zrušení:

javascript
m.route(document.body, '/', {
  '/': {
    onmatch: function (args, requestedPath) {
      if (m.route.get() === requestedPath) return new Promise(function () {});
    },
  },
});

Integrace s třetími stranami ​

V určitých situacích můžete potřebovat spolupracovat s jiným frameworkem, jako je React. Zde je postup, jak to udělat:

  • Definujte všechny své cesty pomocí m.route, jak jste zvyklí, ale ujistěte se, že jej používáte pouze jednou. Použití více směrovacích bodů není podporováno.
  • Když potřebujete zrušit odběry směrování, použijte m.mount(root, null), pomocí stejného kořene, který jste použili m.route(root, ...) na. m.route používá interně m.mount k připojení všeho, takže to není magie.

Zde je příklad použití Reactu:

jsx
class Child extends React.Component {
  constructor(props) {
    super(props);
    this.root = React.createRef();
  }

  componentDidMount() {
    m.route(this.root, '/', {
      // ...
    });
  }

  componentDidUnmount() {
    m.mount(this.root, null);
  }

  render() {
    return <div ref={this.root} />;
  }
}

A zde je přibližný ekvivalent ve Vue:

html
<div ref="root"></div>
javascript
Vue.component('my-child', {
  template: `<div ref="root"></div>`,
  mounted: function () {
    m.route(this.$refs.root, '/', {
      // ...
    });
  },
  destroyed: function () {
    m.mount(this.$refs.root, null);
  },
});
Pager
Předchozí stránkamount(root, component)
Další stránkarequest(options)

Vydáno pod licencí MIT.

Copyright (c) 2024 Mithril Contributors

https://mithril.js.org/route.html

Vydáno pod licencí MIT.

Copyright (c) 2024 Mithril Contributors