yksinkertainen johdatus JavaScriptin Historiarajapintaan

historian API on yksi niistä JavaScript-tekniikoista, jotka jokaisen web-kehittäjän on osattava kylmästi. Ilman sitä, yhdellä napsautuksella takaisin painiketta hyppää suoraan ulos sovelluksesta. Menetät kaikki keskeneräiset työt, ja käyttäjä joutuu aloittamaan kaiken alusta.

onneksi on helppo ratkaisu. HTML5: n virallistamisesta (ja Internet Explorer 10: n julkaisemisesta) lähtien meillä on ollut History API, jonka avulla voit lisätä historialuetteloon ja reagoida taaksepäin ja eteenpäin navigointiin. Tässä artikkelissa, opit miten se toimii-ja voit kokeilla sitä live esimerkki.

mutta ennen kuin mennään eteenpäin, katsotaan tarkemmin ongelmaa.

ennen vanhaan www—sivuilla tehtiin yhtä asiaa-näytettiin juttuja. Kun halusit katsoa jotain muuta, klikkasit linkkiä ja siirryit uuteen URL-osoitteeseen.

JavaScriptin voimistuessa Kehittäjät tajusivat, että jokainen web-sivu voisi olla kokonainen sovellus sellaisenaan. Verkkosivu voi kilpailla työpöytäsovelluksen kanssa! Ongelmana oli, että selaimen Back and Forward-painikkeet eivät sopineet tähän uuteen sovellusmalliin. Käyttäjä saattaa esimerkiksi suorittaa tehtäväsarjan yksisivuisessa verkkosovelluksessa ja odottaa sitten käyttävänsä takaisin-painiketta palatakseen yhden askeleen taaksepäin. Sen sijaan, Takaisin-painike palaisi edelliselle sivulle, tehokkaasti sammuttaa JavaScript-sovellus keskellä mitä se oli tekemässä.

usein tämä käytös ei ollut intuitiivista. Harkitse esimerkiksi sovellusta, joka käyttää XMLHttpRequest object hakemaan uutta tietoa ja päivittämään sivua. Käyttäjälle saattaa näyttää siltä, että he ovat matkalla uudelle sivulle. Mutta jos he tekevät virheen käyttämällä takaisin painiketta, illuusio särkyy ja kaikki menee pieleen.

katsotaanpa tarkemmin. Tässä on esimerkki, jonka avulla voit astua läpi Dictionnaire Infernal, kuuluisa (ja nyt public domain) kirja vuodelta 1818 kuvataan outoja petoja taikauskosta ja mytologiasta. Juju on siinä, että edellinen ja seuraava linkki eivät vie toiselle sivulle. Sen sijaan ne laukaisevat asynkronisen puhelun XMLHttpRequest, joka saa tiedon seuraavaa diaa varten. Sitten, JavaScript-koodi päivittää slide-ruutuun, häiritsemättä sisältöä muun sivun.

tässä on live-versio esimerkistä, täydennettynä History API-tuella. Vaikka kaikki tapahtuu yhdellä sivulla, voit käyttää etu-ja Takapainikkeita siirtyäksesi saumattomasti kuvasta toiseen. Voit jopa käyttää Reload-painiketta (lataa nykyinen dia uudelleen koko sovelluksen uudelleenkäynnistyksen sijaan), ja voit asettaa kirjanmerkkejä, jotka pitävät nykyisen tilan — toisin sanoen, ne johtavat sinut suoraan takaisin dialle, jota parhaillaan katsot.

ja tässä on vanhan koulukunnan versio esimerkistä, joka ei käytä History API: a. Sillä ei ole väliä kuinka pitkälle olet sivunäytöksessä — kun käytät Back-painiketta, hyppäät takaisin edelliselle sivulle. Eteenpäin-ja Reload-painikkeet ovat samalla tavalla rikki. Kirjanmerkit Käynnistä sovellus alusta.

voit ladata kaikki lähdekoodit täältä pelattavaksi. (Se ei kuitenkaan toimi paikallisesti, koska se käyttää XMLHttpRequest objektia verkkopyyntöjen tekemiseen.) Tämän artikkelin loppuosassa kerron, miten kaikki toimii.

esimerkin valmistelu

ennen kuin siirrymme History API: hon, on tärkeää saada perustiedot siitä, miten tämä esimerkki toimii. Se on aika yksinkertaista.

sivu käyttää numeroa pitääkseen kirjaa siitä diasta, jonka se tällä hetkellä näyttää. Kun napsautat Seuraava tai edellinen, koodi muuttaa nykyisen dianumeron. Tämän jälkeen se käyttää omaa goToSlide() – funktiotaan sivun päivittämiseen.

goToSlide() funktio on paikka, jossa todellinen työ tapahtuu. Se aloittaa asykronisen pyynnön käyttäen pahamaineista XMLHttpRequest objektia.

voit itse päättää, miten diasisältö syntyy ja lähetetään takaisin sivun kutsukoodiin. Yleensä sinulla on jonkinlainen reitityskehys, joka laukaisee oikean palvelinpuolen koodin. Palvelinpuolen koodi voi sitten napata diasisällön välimuistista, tietokannasta, tiedostosta tai jopa kovakoodatusta merkintälohkosta.

tässä esimerkissä olen pitänyt asiat mahdollisimman yksinkertaisina. Pyyntö nappaa HTML-merkinnän staattisesta tiedostosta. Joten jos pyydät kolmas dia (suhteellinen URL kuten Slides/3), saat pätkä HTML markup juuri että dia. Varovasti!

kun pyyntö päättyy, selain laukaisee newSlideReceived() tapahtumankäsittelijä. Sitten on vain otettava vastaan saatu merkintä ja lisättävä se sivulle, käyttäen paikkamerkkiä <div>.

muuta ei tarvitse tietää rakentaakseen tämän sivun naiivin version, joka ei tue selainhistoriaa.

historiakohde

history objekti on ollut olemassa lähes JavaScriptin alkuajoista lähtien. Mutta suuren osan elämästään se oli paljon vähemmän voimakas (ja paljon vähemmän hyödyllinen) kuin se on nykyään.

alkuperäisellä history oliolla on vain yksi ominaisuus ja kolme perusmenetelmää. Ominaisuus on length, ja se kertoo kuinka monta merkintää selaimen historialuettelossa on:

alert("You have " + history.length + " pages in the history.");

tämä yksityiskohta on enimmäkseen hyödytön.

kolme alkuperäistä history menetelmiä ovat back() (lähettää kävijän askeleen taaksepäin selaushistoriassa), forward() (lähettää kävijän askeleen eteenpäin) ja go() (ottaa numeerinen siirtymä, joka kertoo selaimelle kuinka monta askelta eteenpäin tai taaksepäin). Kaikki tämä lisää jopa suhteellisen vähän, ellet halua suunnitella omia mukautettuja takaisin ja eteenpäin painikkeita web-sivulla.

HistoryAPI lisää kaksi paljon hyödyllisempää ainesosaa: pushState() menetelmä ja onPopState tapahtuma.

merkinnän lisääminen historialuetteloon

pushState() menetelmä on Historiarajapinnan keskipiste. Sen avulla voit lisätä uuden kohteen nykyisen sivun historialuetteloon. Tältä se näyttää:

tässä vaiheessa voi ihmetellä — mitä järkeä on, jos samalle sivulle on useampi merkintä? Temppu on, että jokainen merkintä on jokin tila liitetty siihen — linkitetty pala tietoa tai objekti, että asetat. Kun käyttäjä astuu taaksepäin historialuettelon läpi, saat vastaavat tilatiedot, jotta voit palauttaa sivun edelliseen versioon.

pushState() menetelmä vaatii kolme argumenttia:

  • tiedot. Ensimmäinen argumentti on mikä tahansa tieto, jonka haluat tallentaa edustamaan tämän sivun nykytilaa. Voit käyttää näitä tietoja sivun palauttamiseen, kun käyttäjä palaa historialuettelon läpi.
  • Otsikko. Toinen argumentti on sivun otsikko, jonka haluat selaimen näyttävän. Tällä hetkellä kaikki selaimet ovat yhtenäisiä jättäessään tämän yksityiskohdan huomiotta. (Eli voi vain ohittaa null.)
  • URL. Kolmas argumentti on URL-osoitteen uusi versio, jonka haluat näyttää sivulle selaimen osoiterivillä. Näin voit lisätä paremman tuen Reload-painikkeelle ja selaimen kirjanmerkeille.

Dictionnaire Infernal slideshow-esimerkkiin on helppo lisätä historiatuki, jota tarvitaan vain dianumeron seuraamiseen. Lisää historialuetteloon aina, kun dia muuttuu.

tässä on lisättävän koodin rivi:

history.pushState(slideNumber, null, null);

huomaat, että tämä koodi ei muuta sivun otsikkoa toisella argumentilla (koska se ei kuitenkaan toimi) eikä muuta URL-osoitetta (näet miten se tehdään hetkessä). Se vain tallentaa dianumeron.

koko kuva, tässä kaksi soittoa history.pushState() oikeassa paikassa-seuraavan ja edellisen linkin tapahtumankäsittelijät:

paluu edelliselle sivulle

kun käytät pushState() – menetelmää, täytyy myös miettiä sen luonnollista vastinetta, onPopState tapahtumaa. Vaikka pushState() menetelmä tuo selaimen historialuetteloon uuden merkinnän, onPopState tapahtuma antaa mahdollisuuden käsitellä sitä käyttäjän palatessa.

ymmärtääksesi, miten tämä toimii, mieti, mitä tapahtuu, jos kävijä astuu kaikkien Dictionnairen infernaalisen esimerkin diakuvien läpi. Kun jokainen uusi dia on ladattu, sivu Lisää historiamerkinnän. Mutta jos käyttäjä astuu taaksepäin takaisin-painikkeen kanssa, mitään ei tapahdu.

tämän puutteen korjaamiseksi on käsiteltävä onPopState tapahtuma, joka käynnistyy jokaisen historianavigoinnin jälkeen. (Tämä sisältää, Jos käytät jotakin historiamenetelmistä, kuten history.back(), sekä silloin, kun käyttäjä napsauttaa selaimen navigointipainikkeita.)

onPopState tapahtuma antaa koodillesi aiemmin tallentamasi tilatiedot pushState(). Tällöin kyseessä on vain dianumero, jonka voi napata state tapahtuma-argumentin ominaisuudesta näin:

var slideNumber = e.State;

sinun tehtäväsi on käyttää valtion Tietoja sivun oikean version palauttamiseen. Nykyisessä esimerkissä se tarkoittaa vastaavan dian lataamista kutsumalla handy goToSlide() – funktiota, joka hoitaa kaiken liukunavigoinnin. Koko koodi on lyhyt ja suoraviivainen:

huomaa, että on tarkistettava, onko on null, mikä tapahtuu joillakin selaimilla, kun sivu ladataan ensimmäistä kertaa eikä tilaa ole tallennettu.

URL: n vaihtaminen

tämän esimerkin nykyinen versio tukee historialuetteloa, mutta ei pelaa mukavasti Reload-painikkeella. Esimerkiksi, jos napsautat läpi kolmannen dian ja sitten päivittää sivun, päädyt takaisin alussa. Löydät itsesi samassa tilanteessa, jos yrität Kirjanmerkki yksi dioja — palaa kirjanmerkki ja aloitat takaisin ensimmäinen dia.

ratkaisu näihin ongelmiin on käyttää History API: ta URL-osoitteen muokkaamiseen. Mutta siihen on tärkeä syy, että jätin tämän askeleen viimeiseksi. Usein historiarajapintaa käyttävät esimerkit muuttavat URL-osoitetta, mutta eivät käytä uutta URL-osoitetta. Tämä voi johtaa verkkosovellukseen, joka katkeaa käyttäjän päivittäessä sitä (rumalla 404-virheellä), tai siirtyy samanlaiselle, mutta hieman erilaiselle versiolle sivusta. Jos et ole varma, miten käsitellä eri URL-osoitteita, ei ole häpeä käyttää yksinkertaistettua lähestymistapaa edellisestä esimerkistä.

sanotaan siis, että olet valmis sukeltamaan, tekemään parempia URL-osoitteita ja pelaamaan hienosti kirjanmerkeillä ja selain päivittää. On olemassa kaksi peruslähestymistapaa:

  • Vaihda URL-sivun nimi kokonaan. Vuonna Dictionnaire Infernal esimerkki, voit muuttaa URL slide1.html, Slide2.html, ja niin edelleen, kun käyttäjä liikkuu dioja. Saalis on, että sinun täytyy joko olla todellisia sivuja näillä nimillä (älä tee sitä, se on hankalaa), tai sinun täytyy määrittää reititys niin, että kun web-palvelin saa pyynnön Slide2.html se toimii koodi, joka luo oikean version sivun.
  • säilytä sama sivun nimi, mutta lisää tiedot kyselymerkkijonoon. Tämä on yksinkertaisempi ja pienemmän mittakaavan lähestymistapa. Kun käyttäjä kulkee diaesityksen läpi, päädyt diaesityksen kaltaisiin URL-osoitteisiin.html?slide=1, sitten diaesitys.html?slide=2, diaesitys.html?slide=3, ja niin edelleen. Etuna tässä lähestymistavassa on, että se on trivially helppo kirjoittaa pieni pala JavaScript, joka tarkistaa kyselyn merkkijono ja varmistaa olet oikealla dia, kun sivu ladataan uudelleen. Et tarvitse mitään palvelinkoodia, jotta tämä toimisi – yksi sivu voi tehdä kaiken.

tässä on muokattu versio pushState() aiemmin näkemäsi puhelu, joka käyttää toista lähestymistapaa. Tämä koodi tunkee dian numeron URL-osoitteen loppuun:

history.pushState(slide, null, "Dictionnaire.html?slide=" + slide);

ja tässä on koodi, joka suoritetaan, kun sivu ladataan uudelleen. Se tarkistaa dian tiedot URL-osoitteesta, ja — jos se löytää oikean numeron-kutsuu goToSlide() funktion lataamaan dian.

nyt et koskaan menetä paikkaasi pujottelussa. Voit kokeilla täydellistä versiota tästä esimerkistä tai ladata kaiken täältä.

lopulliset yksityiskohdat

Historiarajapinta on helppokäyttöinen, mutta sen avulla on myös helppo luoda isompia ongelmia, joita ratkotaan. Nyt kun tiedät, miten kaikki sopii yhteen, tässä muutama neuvo:

  • Jos tönäisee, pitää paukahtaa. pushState() method ja onPopState event ovat yhteistyökumppaneita. Sen, mitä toisen kanssa laittaa, saa takaisin toisen kanssa.
  • älä vaihda URL-osoitetta, ellet ole valmis käsittelemään sitä. On mukavaa vaihtaa URL vastaamaan muuttuvan sivun, mutta sinun täytyy pystyä käsittelemään pyyntöjä jokaisen URL käytät. Jos URL-osoitteesi osoittaa sivulle, jota ei ole olemassa, sovelluksesi katkeaa päivityksiin ja kirjanmerkkeihin.
  • käytä custom state-objektia lisätietojen tallentamiseen. Sinun ei tarvitse pitää kiinni yksinkertaisesta numerosta. Voit laittaa koko mukautetun objektin tilaan, joka voi niputtaa yhteen kaikki tiedot, joita tarvitset monimutkaiseen tehtävään.



Vastaa

Sähköpostiosoitettasi ei julkaista.