jednoduchý úvod do historie API v JavaScriptu
historie API je jednou z těch technik JavaScript, které každý webový vývojář potřebuje znát zima. Bez ní bude jediným kliknutím na tlačítko Zpět vyskočit přímo z vaší aplikace. Ztratíte veškeré probíhající práce a uživatel bude nucen začít znovu.
naštěstí existuje snadné řešení. Od formalizace HTML5 (a vydání aplikace Internet Explorer 10) jsme měli API historie, které vám umožní přidat do seznamu historie a reagovat na navigaci zpět a vpřed. V tomto článku se dozvíte, jak to funguje — a vyzkoušíte si to na živém příkladu.
ale než budeme pokračovat, podívejme se blíže na problém.
za starých časů na webu, webová stránka udělal jednu věc-zobrazení věci. Když jste se chtěli podívat na něco jiného, klikli jste na odkaz a šli na novou adresu URL.
Jak JavaScript rostl silněji, vývojáři si uvědomili, že každá webová stránka může být sama o sobě kompletní aplikací. Webová stránka by mohla soupeřit s desktopovou aplikací! Problém byl v tom, že tlačítka Zpět a vpřed v prohlížeči neodpovídala tomuto novému modelu aplikace. Uživatel může například provést posloupnost úkolů v jednostránkové webové aplikaci a poté očekávat, že pomocí tlačítka Zpět se vrátí o jeden krok zpět. Místo toho se tlačítko zpět vrátí na předchozí webovou stránku a účinně vypne aplikaci JavaScript uprostřed toho, co dělá.
často toto chování nebylo intuitivní. Zvažte například aplikaci, která používá objekt XMLHttpRequest
k načtení nových dat a aktualizaci stránky. Pro uživatele by to mohlo vypadat, že cestují na novou stránku. Pokud však udělají chybu při použití tlačítka Zpět, iluze se rozbije a vše jde bokem.
Pojďme se blíže podívat. Zde je příklad, který vám umožní projít Dictionnaire Infernal, slavnou (a nyní veřejnou doménou) knihou z roku 1818 popisující podivná zvířata z pověr a mytologie. Trik je v tom, že předchozí a další odkazy vás nepřesunou na jinou stránku. Místo toho spustí asynchronní volání prostřednictvím XMLHttpRequest
, které získá informace pro další snímek. Poté kód JavaScript aktualizuje pole snímků, aniž by rušil obsah na zbytku stránky.
zde je živá verze příkladu, kompletní s podporou historie API. I když se vše odehrává na jedné webové stránce, můžete pomocí tlačítek vpřed a vzad hladce přecházet z jednoho obrázku na druhý. Můžete dokonce použít tlačítko obnovit (znovu načte aktuální snímek, spíše než restart celé aplikace), a můžete umístit záložky, které zachovat současný stav — jinými slovy, oni vás rovnou zpátky na snímek, který jste v současné době hledá na.
a tady je old-school verze příkladu, který nepoužívá historii API. Nezáleží na tom, jak daleko jste do boční show – když použijete tlačítko Zpět, skočíte zpět na předchozí webovou stránku. Tlačítka Vpřed a znovu jsou podobně rozbitá. Záložky restartujte aplikaci od začátku.
zde si můžete stáhnout veškerý zdrojový kód, se kterým si můžete hrát. (Nebude však fungovat lokálně, protože používá objekt XMLHttpRequest
k vytváření webových požadavků.) Ve zbytku tohoto článku rozeberu, jak vše funguje.
Příprava příklad:
Než se dostaneme do Historie API, je důležité mít základní znalosti o tom, jak tento příklad funguje. Je to celkem jednoduché.
stránka používá číslo ke sledování snímku, který právě zobrazuje. Po klepnutí na tlačítko Další nebo předchozí kód změní aktuální číslo snímku. Poté použije vlastní funkci goToSlide()
k aktualizaci stránky.
funkce goToSlide()
je místem, kde probíhá skutečná práce. Spustí asychronní požadavek pomocí nechvalně známého objektu XMLHttpRequest
.
je na vás, abyste se rozhodli, jak bude obsah snímku vygenerován a odeslán zpět na volací kód na stránce. Obvykle budete mít nějaký směrovací rámec, který spouští správný kód na straně serveru. Tento kód na straně serveru pak může zachytit obsah snímku z mezipaměti, databáze, souboru nebo dokonce z pevně kódovaného bloku značek.
v tomto příkladu jsem udržoval věci co nejjednodušší. Požadavek popadne značku HTML ze statického souboru. Pokud tedy požadujete třetí snímek (s relativní adresou URL jako Slides / 3), dostanete úryvek značky HTML právě pro tento snímek. Klídek!
po dokončení požadavku prohlížeč spustínewSlideReceived()
obsluhu událostí. Pak je to prostě záležitost přijetí přijaté značky a vložení do stránky pomocí zástupného symbolu <div>
.
to je vše, co potřebujete vědět, abyste mohli stavět naivní verzi této stránky, která nepodporuje prohlížeč historie.
objekt historie
objekt history
existuje téměř od úsvitu JavaScriptu. Ale po většinu svého života byla mnohem méně výkonná (a mnohem méně užitečná) než dnes.
původní history
objekt má pouze jednu vlastnost a tři základní metody. Nemovitost je length
, a to vám řekne, kolik položek se v prohlížeči seznam historie:
alert("You have " + history.length + " pages in the history.");
Tento detail je většinou k ničemu.
tři původní history
metody back()
(pošle návštěvník, jeden krok zpět v historii prohlížení), forward()
(pošle návštěvník, jeden krok vpřed) a go()
(trvá číselný posun, který říká prohlížeči, jak mnoho kroků, aby se jít dopředu nebo dozadu). To vše přispívá k relativně málo, pokud chcete navrhnout vlastní tlačítka zpět a vpřed na webové stránce.
HistoryAPI přidává dvě mnohem užitečnější složky: metodu pushState()
a událost onPopState
.
přidání položky do seznamu historie
metoda pushState()
je středobodem historie API. To vám umožní přidat novou položku do seznamu historie pro aktuální stránku. Tady je to, co to vypadá takto:
V tomto bodě, možná se budete divit — jaký je smysl v tom, že více než jedna položka pro stejné stránce? Trik je v tom, že každá položka má s sebou nějaký stav-propojenou informaci nebo objekt, který jste nastavili. Když uživatel provede kroky zpět v seznamu historie, získáte odpovídající informace o stavu, abyste mohli stránku vrátit do předchozí verze.
metoda pushState()
má tři argumenty:
- Data. Prvním argumentem je jakákoli data, která chcete uložit, aby představovala aktuální stav této stránky. Tyto informace použijete k obnovení stránky, když se uživatel vrátí zpět do seznamu historie.
- název. Druhým argumentem je název stránky, kterou má prohlížeč zobrazit. V současné době jsou všechny prohlížeče sjednoceny při ignorování tohoto detailu. (Takže stačí předat
null
.) - URL. Třetím argumentem je nová verze adresy URL, kterou chcete zobrazit pro stránku v adresním řádku prohlížeče. To vám umožní přidat lepší podporu pro tlačítko Znovu načíst a záložky prohlížeče.
v příkladu Dictionnaire Infernal slideshow je snadné přidat podporu historie vše, co potřebujete ke sledování, je číslo snímku. Přidáte do seznamu historie pokaždé, když se snímek změní.
Tady je řádek kódu, budete muset přidat:
history.pushState(slideNumber, null, null);
všimněte Si, že tento kód není změnit název stránky s druhý argument (protože to stejně nefunguje) a nemění URL (uvidíte, jak se k tomu za chvíli). Jediné, co dělá, je uložit číslo snímku.
pro úplný obrázek jsou zde dvě volání na history.pushState()
na jejich správném místě — obslužné rutiny událostí pro další a předchozí odkazy:
Návrat na předchozí stránku
Při použití pushState()
metody, budete také muset přemýšlet o jeho přírodní protějšek, onPopState
událost. Zatímco metoda pushState()
vloží novou položku do seznamu historie prohlížeče, událost onPopState
vám dává šanci se s ní vypořádat, když se uživatel vrátí.
Chcete-li pochopit, jak to funguje, zvažte, co se stane, když návštěvník projde všemi snímky v pekelném příkladu Dictionnaire. Jakmile je každý nový snímek načten, stránka přidá položku Historie. Pokud však uživatel ustoupí tlačítkem Zpět, nic se nestane.
Chcete-li tento nedostatek odstranit, musíte zpracovat událost onPopState
, která se spustí po každé navigaci v historii. (To zahrnuje, pokud používáte jednu z metod historie, například history.back()
, a také když uživatel klikne na navigační tlačítka prohlížeče.
událostonPopState
poskytuje vašemu kódu informace o stavu, které jste dříve uložili s pushState()
. V tomto případě, je to jen číslo snímku, které můžete chytit z state
vlastnost události argument, tak jako:
var slideNumber = e.State;
Vaším úkolem je používat informace o stavu, aby obnovit správnou verzi stránky. V aktuálním příkladu to znamená načtení odpovídajícího snímku voláním užitečné funkce goToSlide()
, která zpracovává veškerou navigaci snímků. Kompletní kód je krátký a přímočarý:
Všimněte si, že musíte zkontrolovat, jestli e.State
null
, který se stane, že na některé prohlížeče, při načtení stránky pro první čas, a tam je žádný stát zachránil.
Změna adresy URL
aktuální verze tohoto příkladu podporuje seznam historie, ale nehraje se pěkně s tlačítkem Reload. Pokud například kliknete na třetí snímek a poté stránku obnovíte, skončíte zpět na začátku. Ocitnete se ve stejné situaci, pokud se pokusíte vytvořit záložku jednoho ze snímků-vraťte se do záložky a začnete zpět na prvním snímku.
řešením těchto problémů je použití API historie k úpravě adresy URL. Ale je tu důležitý důvod, proč jsem tento krok nechal na poslední chvíli. Příklady, které používají API historie, často mění adresu URL, ale nepoužívají novou adresu URL. To může vést k webové aplikaci, která se rozbije, když ji uživatel obnoví (s ošklivou chybou 404), nebo přejde na podobnou, ale mírně odlišnou verzi stránky. Pokud si nejste jisti, jak zacházet s různými adresami URL, není škoda používat zjednodušený přístup z předchozího příkladu.
řekněme, že jste připraveni se ponořit, vytvářet lepší adresy URL a hrát si pěkně se záložkami a aktualizacemi prohlížeče. Existují dva základní přístupy, které můžete použít:
- úplně změňte název stránky URL. V příkladu Dictionnaire Infernal můžete změnit adresu URL na Slide1.html, Slide2.html, a tak dále, jak se uživatel pohybuje přes snímky. Háček je v tom, že musíte mít buď skutečné stránky s těmito názvy (nedělejte to, je to těžkopádné), nebo musíte nastavit směrování tak, aby váš webový server dostal požadavek na Slide2.html spouští kód, který vytváří správnou verzi stránky.
- ponechte stejný název stránky, ale přidejte informace do řetězce dotazu. Jedná se o jednodušší, menší přístup. Jak uživatel prochází prezentací, skončíte s adresami URL, jako je prezentace.html?slide=1, pak SlideShow.html?slide=2, SlideShow.html?slide=3 a tak dále. Výhodou tohoto přístupu je, že je to triviálně jednoduché napsat kousek Javascriptu, který kontroluje řetězec dotazu a dělá se, že jste na správné klouzat, když se stránka se znovu načte. Nepotřebujete žádný kód serveru, aby to fungovalo-jedna stránka může udělat vše —
zde je upravená verze volání pushState()
, které jste viděli dříve a které používá druhý přístup. Tento kód směsí snímek, číslo na konci URL:
history.pushState(slide, null, "Dictionnaire.html?slide=" + slide);
A zde je kód, který se spustí, když se stránka znovu načte. Zkontroluje informace o snímku v URL a — pokud najde správné číslo-zavolá funkci goToSlide()
pro načtení snímku.
nyní už nikdy neztratíte své místo v prezentaci. Můžete si vyzkoušet kompletní verzi tohoto příkladu nebo si vše stáhnout zde.
Poslední podrobnosti
historie API je snadno ovladatelný, ale také usnadňuje vytvářet větší problémy, které vyřešíte. Nyní, když víte, jak vše do sebe zapadá, zde je několik posledních rad:
- Pokud stisknete, musíte pop.
pushState()
metoda aonPopState
událost jsou partnery. Co dáte do jednoho, dostanete se zpět s druhým. - neměňte adresu URL, pokud nejste připraveni ji zpracovat. Je hezké změnit adresu URL tak, aby odrážela měnící se stránku, ale musíte být schopni zpracovat požadavky na každou adresu URL, kterou používáte. Pokud vaše adresa URL ukazuje na stránku, která neexistuje, aplikace se přeruší při obnovování a záložkách.
- pro uložení více informací použijte objekt vlastního stavu. Nemusíte se držet jednoduchého čísla. Můžete dát celý vlastní objekt do stavu, který může spojit všechny informace, které potřebujete pro složitý úkol.