Helpotusta AngularJS:n reititykseen Angular UI Routerilla

Vaikka AngularJS:ssä on sisäänrakennettu reititys, saatat joskus kokea sen rajoittavaksi; Angular UI Router -kehys voi auttaa helpottamaan tuskaa. AngularJS:n natiivin reititystoteutuksen tehtävänä on alustaa kontrollerit, jotka vastaavat sovelluksen reittejä. Vaikka tämä toiminnallisuus toimii hyvin perusskenaarioissa, edistyneissä tilanteissa huomaat nopeasti, että Angularin natiivi reititys:

  • Vaattaa sinut muuttamaan URL-merkkijonoja manuaalisesti koko koodipohjassasi, kun URL-osoite muuttuu.
  • Vaattaa sinut muistamaan reittisyntaksin sanatarkasti, jotta voit navigoida sivulle.
  • Ei tarjoa sisäkkäisiä näkymiä.
  • Ei tarjoa nimettyjä näkymiä.
  • Ei anna sinun siirtää dataa navigoinnin aikana.

Vaihtoehtoisesti Angular UI Router -kehys on abstraktiokerros reititykselle, jossa on deklaratiivisempi lähestymistapa navigointiin. UI Router -kehys täyttää myös joitakin natiivin toteutuksen aukkoja tarjoamalla sisäkkäisiä ja nimettyjä näkymiä, mahdollistaa tietojen siirtämisen näkymien välillä ja paljon muuta.

Angular UI Router -kehys on reitityksen abstraktiokerros, jossa on deklaratiivinen lähestymistapa navigointiin

Tässä artikkelissa opit rakentamaan yksinkertaisen sovelluksen, joka käyttää UI Router -kehystä. Matkan varrella tutustut tiloihin, riippuvuuksien ratkaisemiseen ja opit erilaisia navigointitapoja.

Tilojen ymmärtäminen

Parempi tapa ymmärtää ongelmaa, jonka UI Router -kehys toivoo ratkaisevansa, on ehkä miettiä webin luonnetta. Useimmissa sovelluksissa, kun luot linkin sivulle, määrittelet nimenomaisen URL-polun. Jos esimerkiksi haluaisit siirtyä sivustosi Tuotteet-sivulle, URL-osoite voisi olla seuraavanlainen:

Code Sample 1: Version 2 Flexible Container

http://www.example.com/products

Tässä tilanteessa on kaksi ongelmaa. Ensimmäinen on se, että sinun on muistettava tarkka kirjaimellinen polku Tuotteet-sivulle joka kerta, kun luot linkin. Vaikka tässä annettu esimerkki saattaa olla helppo muistaa, monet todelliset URL-osoitteet eivät ole yhtä helposti muistissa. Seuraavaan ongelmaan törmää, kun väistämätön tapahtuu ja joku päättää muuttaa polun joksikin muuksi. Kun URL-osoite muuttuu, sinun on varmistettava, että kaikki olemassa olevat linkit päivitetään osoittamaan uuteen paikkaan.

Etkö sen sijaan, että sinun pitäisi seurata URL-polkuja sanatarkasti, etkö mieluummin vain sanoisi sovellukselle, että ”siirry tuotesivulle”? Kun annat sovelluksen huolehtia itse navigoinnista, sinun ei tarvitse tietää kirjaimellista polkua, ja olet suojassa muutosten väistämättömyyden aiheuttamilta rikkinäisiltä linkeiltä. Tilojen käyttäminen antaa sinulle tämän tason joustavuutta. Tila kapseloi URL-osoitteen sijainnin, tilan nimen, näkymän erikoistuneet tiedot, tunnistaa tavan paikantaa tai luoda näkymä, ja se voi jopa paljastaa mukautettuja tapahtumia.

Introducing Angular UI Router

Angular UI Router on kehys, joka korvaa kokonaan AngularJS:ssä käytettävissä olevan natiivin reitityksen. UI Router on hyvin samankaltainen kuin natiivi AngularJS:n reititys siinä mielessä, että sovellukset koostuvat kuoresta, joka pitää sisällään dynaamisen sisällön paikanhaltijan. Kuvassa 1 havainnollistetaan, miten sovelluksen kuori isännöi elementtiä, joka käyttää ui-view-direktiiviä. Kun tilasääntöjä arvioidaan kehyksessä, HTML-sisältö renderöidään sijoituspaikan haltijan sisälle.

Kuva 1: UI Router -kehys lisää HTML-sisältöä sivulla olevaan sijoituspaikan haltijaan.

Angular UI Router on kehys, joka korvaa kokonaan AngularJS:ssä käytettävissä olevan natiivin reitityksen.

HTML-sisällön renderöinnin lisäksi UI Router -kehys tukee URL-reititystä, kykyä ratkaista riippuvuuksia ennen kontrollerien alustamista, nimettyjä ja sisäkkäisiä näkymiä, apuohjelmasuodattimia, tilanmuutostapahtumia ja deklaratiivisia siirtymiä tilojen välillä.

Navigointi tilojen välillä

Tilojen välillä voi siirtyä muutamalla eri tavalla. Ensimmäinen tapa on ui-sref-direktiivi. Tunnet luultavasti HTML:n ankkuritunnisteen href-attribuutin (joka edustaa hypertekstiviittausta); vastaavasti ui-sref-direktiivi viittaa tilaviittaukseen. Direktiiviä käytetään ilmoittamalla tilan nimi ankkuriin sovelletulla ui-sref-direktiivillä. Esimerkiksi:

<a ui-sref="about">About Us</a>

Kun UI Router -kehys arvioi tätä direktiiviä, ankkuri muutetaan niin, että sillä on asianmukainen URL-arvo. Esimerkiksi:

<a ui-sref="about" href="#about">About Us</a>

Huomaa, että elementti päivitetään sisältämään href-attribuutti, jonka arvo vastaa sitä, miten URL-osoite on päivitettävä, jotta voidaan siirtyä Tietoja meistä -sivulle. ui-sref-direktiivi on varsin joustava. Se tukee yksinkertaisia skenaarioita sekä tapoja käsitellä sisäkkäisiä tiloja ja jopa parametrisoituja arvoja.

Seuraava lähestymistapa tilojen väliseen navigointiin on käyttää $state-objektin metodia, joka on Angular-ohjaimen käytettävissä. Tässä seuraavassa pätkässä näet, miten navigate-metodi on toteutettu kutsumaan $state.go ja siirtymään sovelluksen about-tilaan.

angular.module('app') .controller('PageController', );

$state-objekti injektoidaan UI Router -kehyksen toimesta, ja se sisältää useita metodeja, jotka auttavat hallitsemaan ja käsittelemään sovelluksen tilaa. Tämän arvo on siinä, että käsket sovelluksen ”siirtyä” about-tilaan ja olet vapautettu tietämästä kirjaimellista URL-polkua sivulle.

Lataaminen ja asennus

On olemassa useita eri tapoja, joilla voit päästä käsiksi UI Router -kehykseen. Voit ladata uusimman version suoraan GitHub-arkistosta osoitteesta https://github.com/angular-ui/ui-router. Vaihtoehtoisesti voit asentaa kehyksen Bowerin tai NuGetin kautta tai jopa sisällyttää CDN-linkkejä sivuillesi; molemmat ovat saatavilla osoitteessa http://cdnjs.com/libraries/angular-ui-router.

Angular UI Routerin käyttäminen

Seuraavassa opetusohjelmassa näytetään, miten rakennetaan yksinkertainen staattinen sisältöpohjainen sovellus UI Router -kehyksen avulla. Kuvassa 2 on esitetty kotisivun esimerkkisovellus, jonka opit rakentamaan tätä artikkelia lukiessasi. Tästä kuvakaappauksesta näet sovelluksen kuoren ja sen, miten kotisivun sisältö ruiskutetaan sijoituspaikkaan ui-view-direktiivin avulla.

Kuva 2 : Sovelluksen etusivu ja oletustila

Vaihtamalla tilaa voit siirtyä yhteystietosivulle, kuten kuvassa 3 näkyy. Yhteydenottosivun mekanismi käyttää $state-olion go-metodia välittämällä metodille tilan nimen.

Kuva 3 : Yhteydenottosivu

Seuraava tila liittyy artikkelin luettelosivuun, kuten kuvassa 4 näkyy. Tässä artikkelitietojen joukko asetetaan näkymän saataville sen jälkeen, kun UI Framework on injektoinut raa’at arvot kontrolleriin. Navigointia tällä sivulla helpottaa ui-sref-direktiivi, jonka avulla voidaan deklaratiivisesti ilmaista sovelluksen tila, johon halutaan navigoida.

Kuva 4 : Artikkelien luettelosivu

Viimeinen sivu, joka on esitetty kuvassa 5, osoittaa, miten sovelluksessa käytetään sisäkkäistä tilaa.

Kuva 5 : Artikkelien luettelosivu

Konfigurointi

Voidaksesi aloittaa työskentelyn UI Router -kehyksen kanssa, sinun on konfiguroitava sivu. Ensimmäinen vaihe on lisätä sovelluksen nimi sivun HTML-elementin ng-app-attribuuttiin. Tässä sovelluksen nimi on yksinkertaisesti app.

< html ng-app="app">

Seuraavaksi sinun on lisättävä ui-view-direktiivi sivun elementtiin, jotta se toimii kehyksen injektoiman sisällön paikanhaltijana. Tässä tapauksessa direktiivi lisätään div-elementtiin.

< div ui-view></div>

Viimeiseksi sivulla on viitattava sekä Angular- että Angular UI -reitittimeen.

<script src="scripts/lib/angular.min.js"></script><script src="scripts/lib/angular-ui-router.min.js"></script><script src="scripts/app/app.js"></script>

Tässä koodinpätkässä on myös viittaus script/app-kansiossa olevaan app.js-skriptiin, joka sisältää koodin Angular-sovelluksen alustamiseksi. Initialisointiprosessissa toteutetaan suurin osa asetuksista ja käyttöliittymästä UI Router -kehyksen kanssa.

Tilojen määrittely

Kuten aiemmin todettiin, UI Router -kehyksen perustana on erilaisten tilojen käyttö sovelluksessa. Käyttämällä kutakin näistä tiloista sovellus voi siirtyä tai muodostaa itsensä uudelleen olosuhteisiin sovelluksen elinkaaren aikana. Seuraavassa osiossa esitellään, miten sovelluksen tilat määritellään; kaikki koodi on toteutettu app.js-tiedostossa. Jokaista osiota tarkastellaan erikseen, mutta jos haluat nähdä koko alustusskriptin, katso Listaus 1.

Ensimmäinen vaihe on määrittää UI Router AngularJS-sovellukseen. Kun olet nimennyt moduulin, sinulla on mahdollisuus rekisteröidä UI Router -kehys sovelluksen riippuvuudeksi lisäämällä literaali ui.router riippuvuuksien joukkoon. (Huomaa, miten kommentti tarkoittaa paikanhaltijaa myöhemmässä pätkässä olevaa koodia varten.)

angular.module('app', ) .config(/* add configuration here */);

Kun moduuli on määritelty ja riippuvuudet rekisteröity, sovellus asetetaan suorittamaan anonyymi funktio, joka suoritetaan sovelluksen konfigurointivaiheessa. Tässä funktioon ruiskutetaan muutama resurssi, jotka ovat merkityksellisiä UI Router -kehyksen kannalta.

 

Objekti $stateProvider sisältää state-metodin, jonka avulla voidaan määritellä rakeisia sovelluksen tiloja, jotka voivat tai eivät voi olla yhteneväisiä URL-osoitteen muutosten kanssa. $urlRouterProvider on objekti, jonka avulla voit hallita selaimen sijainnin hallintaa ja havainnointia. UI-reitittimen yhteydessä $urlRouterProvideria käytetään apuna navigointiskenaarion määrittelyssä. Kutakin näistä objekteista käsitellään tarkemmin tulevissa koodinpätkissä. (Huomaa jälleen, että seuraavat koodinpätkät sijoitetaan edellisen koodinpätkän sijoituskommentin paikkaan.)

Jokainen sovelluksen tila määritellään antamalla nimi ja kertomalla kehykselle, mistä näkymän markup löytyy. Tässä home-tila määritellään antamalla url:n juuripaikka ja arvo templateUrl-ominaisuudelle.

$stateProvider .state('home', { url: '/', templateUrl: '/partials/home.html' })

Tämä kertoo sovellukselle, että se lataa home.html-tiedoston sisällön ui-view-paikanhaltijaan, kun käyttäjä navigoi sovelluksen juurelle. Tässä alkaa näkyä yksi tilakeskeisen reitityksen eduista. Jos jostain syystä haluaisit kotitilan URL-osoitteen osoittavan /home-osoitteeseen pelkän juuripaikan (/) sijasta, tämä muutos tarvitsisi tapahtua vain tässä konfiguraatiossa. Tämä tila luopuu kaikista lisäasetuksista ja lataa selaimeen staattisen sivun. Voi olla muitakin tilanteita, joissa tilaan halutaan liittää tietty ohjain.

Kontaktitila on määritetty lataamaan contact.html-sivun markup-merkintä ui-view-paikanhaltijaan. Sen lisäksi, että ContactsController-ohjain tekee perus replace-operaation, se liitetään myös näkymään, joka on skaalattu sen DOM-elementin tasolle, joka isännöi ui-view-direktiiviä.

 .state('contact', { url: '/contact', templateUrl: '/partials/contact.html', controller: 'ContactController', })

Kuten kuvassa 3 näkyy, Contact-sivulla on painike, jolla voi siirtyä Articles-sivulle. Navigointi tapahtuu ContactsControllerissa, ja se havainnollistaa, miten kontrolleri johdotetaan UI Router -puitteiston pyynnöstä lataamaan näkymään.

Artikkeli-sivun tila vie konfigurointia askeleen pidemmälle lisäämällä objektiin arvoja, jotka ratkaisevat kaikki objektissa määritellyt konfiguroidut arvot. Tämän tilan tarkoituksena on renderöidä luettelo sivustolla saatavilla olevista artikkeleista. Tämä tila on määritetty siten, että artikkelitiedot ovat ohjaimen käytettävissä ennen sen instantiointia. Seuraavassa pätkässä tila määrittelee resoluutioobjektin arvon.

 .state('articles', { url: '/articles', templateUrl: '/partials/articles.html', resolve: { articles: 'ArticlesService' }, controller: 'ArticlesController' })

Tässä tapauksessa articles-ominaisuus osoittaa merkkijonoon ArticlesService. Kun annat merkkijonon arvona resolve-ominaisuudelle, kehys ottaa yhteyttä samalla nimellä rekisteröityyn palveluun ja ratkaisee palvelun lopulliseen arvoonsa. Tässä tapauksessa ArticlesService palauttaa lupauksen, joten siihen liittyvää ohjainta ei instantioida ennen kuin palvelun lupaus on ratkaistu ja lopullinen objekti on käytettävissä ohjaimen injektoitavana arvona. ArticlesServicen toteutus on saatavilla Listing 3:ssa.

Kun artikkeliluettelo on renderöity käyttäjälle kuvassa 4 esitetyllä tavalla, käyttäjä voi valita artikkelin ja porautua sivuston sisältöön. Tätä toimintoa edustaa sisäkkäinen tila. Huomaa, että tilan nimessä on piste (.) artikkelien ja artikkelin välissä, mikä ilmaisee vanhempi- ja lapsisuhdetta tilojen välillä.

 .state('articles.article', { url: '/:pageName', templateUrl: function ($stateParams) { return '/partials/articles/' + $stateParams.pageName + '.html'; } });

Tässä sovelletaan erityissääntöä siihen, miten url-ominaisuus arvioidaan. Koska kyseessä on sisäkkäinen näkymä (kuten piste valtion nimessä osoittaa), url-ominaisuuden arvo ketjutetaan vanhemman valtion url-arvon kanssa. Tämä tarkoittaa, että kaikilla vastaavilla tiloilla on URL-osoite, joka alkaa kirjaimella /articles ja sisältää sitten artikkelin sivunimen.

Kaksoispisteen (:) läsnäolo viittaa URL-parametriin. Kun URL-osoitteeseen lisätään parametri, tilamääritelmästä tulee riittävän joustava käsittelemään mitä tahansa tilaa, joka vastaa sen suhdetta vanhemman tilan kanssa. Tässä tilassa on myös funktio, joka suoritetaan templateUrl:n arvon palauttamiseksi. Funktion käyttäminen tässä antaa mahdollisuuden käyttää tilan url-osoitteessa määriteltyjä parametreja. Mikä tahansa nimi, jonka annat parametrille url-ominaisuudessa, vastaa $stateParams-olion ominaisuuden nimeä. Siksi tämä tila ottaa URL-osoitteessa välitetyn pageName-parametrin, jota käytetään templateUrl-funktiossa yksittäisten sisältötiedostojen käyttämiseen, jotka lopulta injektoidaan ui-view-direktiiviä isännöivään elementtiin.

Tämä on viimeinen sovelluksessa määritelty tila. Jos haluat nähdä, miten kaikki tilat on toteutettu varsinaisessa alustusskriptissä, katso Listaus 1.

Viimeinen komento, joka sovellukselle pitää antaa, on se, mitä tehdään, jos käyttäjä yrittää käyttää URL-osoitetta, jota ei ole määritelty configure-metodissa. Käyttämällä $urlRouterProvider-olion otherwise-metodia kaikki tunnistamattomat URL-osoitteet hylätään ja sovellus ohjataan oletussijaintiin. Tässä tapauksessa sovellus on määritetty ohjautumaan juuri-URL:ään, jos annettu URL-osoite ei vastaa määriteltyä tilaa.

$urlRouterProvider.otherwise('/');

Nyt kun jokainen sovelluksen tila on määritetty, voit alkaa kääntää huomiosi ArticlesService-palvelun rakentamiseen.

Datan ratkaiseminen artikkelipalvelulla

Artikkelin tilan konfigurointiin sisältyy arvo resolve-vaihtoehdolle. Tämä objekti on konfiguroitu siten, että articles-ominaisuuteen on asetettu merkkijonoarvo ArticlesService (katso asiayhteys Listauksessa 1). Merkkijonon antaminen resolve-oliolle käskee kehystä etsimään sovellukseen rekisteröidyn palvelun ja ratkaisemaan palvelun lopulliseen arvoonsa. ArtikkelitPalvelu on toteutettu palauttamaan lupaus.

angular.module('app').factory('ArticlesService', ); return deferred.promise; }]);

Tässä palvelu käyttää $q-palvelua luodakseen lupauksen, jolla palautetaan joukko. Tässä tapauksessa arvot on kovakoodattu, mutta reaalimaailmassa saatetaan joutua käyttämään etäpalvelinta tietojen toimittamiseksi. Joka tapauksessa palvelun on oltava täysin ratkaistu, ennen kuin reitityskehys siirtää suorituksen siihen liittyvälle ohjaimelle. Siksi artikkelin tilaa kutsuttaessa kontrollerille välitetään viime kädessä riippuvuutena joukko artikkeliobjekteja.

Resolvoitujen tietojen käyttäminen ArticlesControllerissa

Yksi UI Router -reititinkehyksen käyttämisen eduista on kyky pakottaa huolenaiheiden erottaminen. Koska Articles-tila toteuttaa resolve-olion, artikkelien raaka joukko injektoidaan kontrolleriin.

angular.module('app') .controller('ArticlesController', );

Tämä lähestymistapa on parempi kuin se, että ArticlesControllerilta vaaditaan ArticlesService-palvelun ”tuntemista”, koska on paljon helpompi pilkata raakaa joukkoa objekteja testausta varten sen sijaan, että joutuisi käsittelemään itse palvelun pilkkaamista. Sovelluksen kontrollereiden täydellinen toteutus löytyy Listauksesta 2.

Artikkeliluettelon renderöinti

Nyt kun sovellus on navigoinut artikkelin tilaan ja kontrollerilla on resolved articles array asetettu scopeen, näkymä on nyt valmis renderöitäväksi. Artikkelit-näkymä koostuu kahdesta osasta. Ensimmäinen on toinen div-sijoituskappale, joka käyttää ui-view-direktiiviä luodakseen sisäkkäisen näkymän. Toinen osa on järjestämätön luettelo sivustolla saatavilla olevista artikkeleista. Rakentamalla näkymä näin voit napsauttaa eri artikkelien otsikoita samalla, kun artikkeliluettelo pysyy sivulla. (Tästä on esimerkki kuvassa 5.) Tämä on mahdollista, koska sivun sisältö ladataan artikkelitason ui-view-näkymään, kun taas koko sivu renderöidään sovelluksen kuoren ui-view-näkymässä. Sovelluksen kuoren täydellinen toteutus on luettelemassa 4.

Oheinen koodinpätkä havainnollistaa, miten artikkelinäkymä toteuttaa sisäkkäisen näkymän.

<div ui-view> <!-- default content goes here --></div>...<ul class="list-group"> <li class="list-group-item" c> <a ui-sref="articles.article({pageName: '{{article.pageName}}'})"> {{article.title}}</a> </li></ul>

Tässä merkinnässä käytetään UI Router -puitteistoa kolmella tavalla. Ensinnäkin div-elementti käyttää ui-view-direktiiviä paikanhaltijana, ja kuten kommentissa sanotaan, voit välittää oletussisältöä renderöitäväksi paikanhaltijassa ennen kuin kehys renderöi mitään sisältöä. Listaus 5 havainnollistaa, kuinka staattista viestiä käytetään sivun sijoitussisällönä ennen kuin mitään sisältöä ladataan näkymään.

Toiseksi anchor-elementissä käytetään ui-sref-direktiiviä. Tämä viestii UI Router -kehykselle, että se käsittelee tätä linkkiä kehyksen kontekstissa ja renderöi lopulta vakiomuotoisen href-arvon, joka vastaa ilmoitetun tilan URL-osoitetta sovelluskonfiguraatiossa määriteltyjen asetusten perusteella (ks. Listaus 1).

Kolmas tapa, jolla kehystä käytetään, on se, että ui-sref-direktiivin arvo hyväksyy lausekkeen, joka tuottaa oikean URL-arvon sisäkkäiselle tilalle. Tässä sisäkkäisen tilan hierarkiaan (tässä tapauksessa articles.article) välitetään hash, jossa pageName-arvo sidotaan saapuvan artikkelin pageNameen. Kun UI Router -kehys arvioi tätä lauseketta, luodaan vastaava URL-arvo jokaiselle artikkelille, joka vastaa määriteltyjä tilasääntöjä.

More Abstract Navigation

Viimeisenä toteutettavana kontrollerina on ContactController, joka käyttää state-parametrin go-metodia sovelluksen navigoimiseksi uuteen tilaan.

app.controller('ContactController', );

Tässä yksinkertaisesti kutsumalla go:ta tilan nimen kanssa kontrollerisi huolehtii vain sen tilan ilmoittamisesta, johon haluat siirtyä, sen sijaan, että yrittäisit pitää kirjaa sovelluksen konkreettisesta reitityssuunnitelmasta.

Johtopäätökset

Niinkin, että AngularJS:n mukana tulee funktionaalinen reititystoteutuksen toteutus, huomaat nopeasti tilapohjaisen reitityskehyksen käyttämisen hyödyt ei-triviaaleissa sovelluksissa. UI Router -kehys tarjoaa helppoja tapoja määritellä tiloja, ratkaista riippuvuuksia ja hyödyntää sisäkkäisiä näkymiä. Jos haluat vielä enemmän tietoa siitä, mitä kehyksellä voi tehdä, muista käydä projektin kotisivulla GitHubissa osoitteessa https://github.com/angular-ui/ui-router/.

Vastaa

Sähköpostiosoitettasi ei julkaista.