Egyszerűbb AngularJS Routing az Angular UI Routerrel

Bár az AngularJS beépített útválasztással rendelkezik, ez néha korlátozó lehet; az Angular UI Router keretrendszer segíthet enyhíteni a fájdalmat. A natív AngularJS útválasztási implementáció felelős az alkalmazás útvonalainak megfelelő vezérlők inicializálásáért. Bár ez a funkcionalitás jól működik az alapvető forgatókönyvekben, haladó helyzetekben gyorsan rájön, hogy az Angular natív útválasztása:

  • Kényszeríti, hogy kézzel módosítsa az URL-ek karakterláncát a kódbázisában, amikor egy URL megváltozik.
  • Kényszeríti, hogy szó szerint megjegyezze az útvonal szintaxisát az oldalra navigáláshoz.
  • Nem kínál egymásba ágyazott nézeteket.
  • Nem kínál nevesített nézeteket.
  • Nem teszi lehetővé az adatok átadását a navigáció során.

Az Angular UI Router keretrendszer alternatívaként egy absztrakciós réteg az útválasztáshoz, amely deklaratívabb megközelítést kínál a navigációhoz. Az UI Router keretrendszer a natív implementáció néhány hiányosságát is kitölti azáltal, hogy beágyazott és nevesített nézeteket biztosít, lehetővé teszi az adatok átadását a nézetek között, és még sok minden mást.

Az Angular UI Router keretrendszer egy absztrakciós réteg az útválasztáshoz, amely a navigáció deklaratív megközelítésével rendelkezik

Ez a cikk megtanul egy egyszerű alkalmazást készíteni, amely az UI Router keretrendszert használja. Ennek során megismerkedik az állapotokkal, a függőségek feloldásával, és megtanulja a navigáció különböző módszereit.

Az állapotok megértése

Az UI Router keretrendszer által megoldani remélt problémát talán úgy tudja a legjobban értékelni, ha figyelembe veszi a web természetét. A legtöbb alkalmazásban, amikor egy oldalra mutató linket hozunk létre, egy explicit URL-útvonalat határozunk meg. Ha például a webhelyünk Termékek oldalára szeretnénk navigálni, akkor egy olyan URL-t adhatunk meg, mint:

Code Sample 1: Version 2 Flexible Container

http://www.example.com/products

Ezzel a helyzettel két probléma van. Az első az, hogy minden alkalommal, amikor létrehozza a hivatkozást, emlékeznie kell a Termékek oldal pontos szó szerinti elérési útvonalára. Bár az itt megadott példa könnyen felidézhető, sok valós URL-cím nem jegyezhető meg ilyen könnyen. A következő problémával akkor találkozik, amikor megtörténik az elkerülhetetlen, és valaki úgy dönt, hogy megváltoztatja az elérési utat valami másra. Amikor egy URL megváltozik, akkor meg kell győződnie arról, hogy az összes meglévő linket frissíti, hogy az új helyre mutasson.

Ahelyett, hogy szó szerint nyomon kellene követnie az URL-útvonalakat, nem lenne jobb, ha egyszerűen azt mondaná az alkalmazásnak, hogy “menjen a Termékek oldalra”? Azzal, hogy hagyja, hogy az alkalmazás foglalkozzon a navigációval, megszabadul a szó szerinti elérési útvonal ismeretétől, és megóvja magát a változások elkerülhetetlensége által okozott törött linkektől. Az állapotok használata ilyen szintű rugalmasságot biztosít. Egy állapot magába foglal egy URL-helyet, az állapot nevét, a nézet speciális adatait, azonosítja a nézet megtalálásának vagy létrehozásának módját, és akár egyéni eseményeket is megjeleníthet.

Az Angular UI Router bemutatása

Az Angular UI Router egy olyan keretrendszer, amely teljes mértékben helyettesíti az AngularJS-ben elérhető natív útválasztást. Az UI Router nagyon hasonlít a natív AngularJS útválasztáshoz abban, hogy az alkalmazások egy héjból állnak, amely egy helyőrzőt tartalmaz a dinamikus tartalom számára. Az 1. ábra bemutatja, hogy az alkalmazáshéj hogyan ad otthont egy olyan elemnek, amely az ui-view direktívát használja. Ahogy az állapotszabályok kiértékelődnek a keretrendszerben, a HTML-tartalom megjelenik a helytartón belül.

1. ábra: Az UI Router keretrendszer HTML-tartalmat ad hozzá egy helytartóhoz az oldalon.

Az Angular UI Router egy olyan keretrendszer, amely teljes mértékben helyettesíti az AngularJS-ben elérhető natív útválasztást.

A HTML-tartalom megjelenítésén túl az UI Router keretrendszer támogatja az URL-továbbítást, a függőségek feloldásának lehetőségét a vezérlők inicializálása előtt, a megnevezett és egymásba ágyazott nézeteket, a segédszűrőket, az állapotváltozási eseményeket és az állapotok közötti deklaratív átmeneteket.

Az állapotok közötti navigálás

A különböző állapotok között többféle módon lehet mozogni. Az első mód az ui-sref direktíva. Valószínűleg ismered a HTML anchor tag href attribútumát (amely egy hipertext-hivatkozást jelöl); hasonlóan az ui-sref direktíva is egy állapothivatkozásra utal. A direktívát úgy használjuk, hogy egy állapotnevet deklarálunk egy anchorra alkalmazott ui-sref direktívával. Például:

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

Amint az UI Router keretrendszer kiértékeli ezt a direktívát, a horgony átalakul a megfelelő URL-értékre. Például:

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

Figyeljük meg, hogy az elem frissül, hogy tartalmazzon egy href attribútumot egy olyan értékkel, amely megfelel annak, ahogyan az URL-t frissíteni kell a Rólunk oldalra való navigáláshoz. Az ui-sref direktíva meglehetősen rugalmas. Támogatja az egyszerű forgatókönyveket, valamint az egymásba ágyazott állapotok és akár paraméterezett értékek kezelésének módjait is.

A következő megközelítés az állapotok közötti navigációhoz az, hogy az Angular vezérlő számára elérhető $state objektumból egy módszert használunk. A következő részletben láthatjuk, hogyan valósul meg a navigate metódus a $state.go meghívásához és az alkalmazás about állapotba való átmenetéhez.

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

A $state objektumot az UI Router keretrendszer injektálja, és számos metódust tartalmaz, amelyek segítenek az alkalmazás állapotának kezelésében és manipulálásában. Ennek az az értéke, hogy megmondja az alkalmazásnak, hogy “menjen” az about állapotba, és megszabadul az oldal szó szerinti URL elérési útvonalának ismeretétől.

Letöltés és telepítés

Az UI Router keretrendszerhez többféle módon is hozzáférhet. A legfrissebb verziót közvetlenül a https://github.com/angular-ui/ui-router GitHub tárolóból töltheti le. Alternatívaként telepítheti a keretrendszert Bower vagy NuGet segítségével, vagy akár CDN linkeket is beilleszthet az oldalaiba; mindkettő elérhető a http://cdnjs.com/libraries/angular-ui-router címen.

Az Angular UI Router használata

A következőkben egy bemutatót olvashat, amely bemutatja, hogyan készíthet egy egyszerű statikus tartalomalapú alkalmazást az UI Router keretrendszer segítségével. A 2. ábra a kezdőlap mintaalkalmazást ábrázolja, amelyet a cikk elolvasása során megtanul építeni. Ezen a képernyőképen látható az alkalmazás héja, és az, hogy a kezdőlap tartalma hogyan kerül beillesztésre a helytartóba a ui-view direktíva segítségével.

2. ábra : A kezdőlap és az alkalmazás alapértelmezett állapota

A 3. ábrán látható módon az állapotokat megváltoztatva a kapcsolatfelvételi oldalra navigálhat. A kapcsolatfelvételi oldalon a mechanizmus a $state objektum go metódusát használja az állapot nevének átadásával a metódusnak.

3. ábra : A kapcsolatfelvételi oldal

A következő állapot a cikk listaoldalához kapcsolódik, ahogy a 4. ábrán látható. Itt a cikkadatok egy tömbje válik elérhetővé a nézet számára, miután a nyers értékeket a UI Framework befecskendezte a vezérlőbe. A navigációt ezen az oldalon az ui-sref direktíva könnyíti meg, amely lehetővé teszi, hogy deklaratívan kifejezzük az alkalmazás állapotát, amelyhez navigálni szeretnénk.

4. ábra : A cikkek listája oldal

Az 5. ábrán látható utolsó oldal azt mutatja, hogy az alkalmazásban hogyan használják az egymásba ágyazott állapotot.

5. ábra : A cikkek részletező oldala

Konfiguráció

Az UI Router keretrendszerrel való munka megkezdéséhez az oldalt konfigurálni kell. Az első lépés az alkalmazás nevének beírása az oldal HTML elemének ng-app attribútumába. Itt az alkalmazás neve egyszerűen app.

< html ng-app="app">

A következő lépésben az ui-view direktívát kell hozzáadni az oldal egyik eleméhez, hogy a keretrendszer által befecskendezett tartalom helytartójaként szolgáljon. Ebben az esetben a direktíva egy div elemhez kerül hozzáadásra.

< div ui-view></div>

Végül hivatkoznia kell mind az Angular, mind az Angular UI Routerre az oldalon.

<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>

Ez a kódrészlet tartalmaz hivatkozást az app.js szkriptre is a script/app mappában, amely az Angular alkalmazás inicializálásának kódját tartalmazza. Az inicializálási folyamat az, ahol a legtöbb beállítás és az UI Router keretrendszerrel való interfész megvalósul.

Állapok definiálása

Mint korábban említettük, az UI Router keretrendszer alapja a különböző állapotok használata az alkalmazásban. Az egyes állapotokhoz való hozzáféréssel az alkalmazás az alkalmazás életciklusán belüli körülményekhez igazodva navigálhat, vagy újraképezheti magát. A következő szakasz bemutatja, hogyan kell definiálni az alkalmazás állapotait; az összes kód az app.js fájlban kerül implementálásra. Az egyes szakaszokat külön-külön vizsgáljuk, de ha a teljes inicializálási szkriptet szeretné látni, tekintse meg az 1. listázást.

Az első lépés az UI Router konfigurálása az AngularJS alkalmazásban. A modul elnevezése után lehetősége van az UI Router keretrendszert az alkalmazás függőségeként regisztrálni a függőségi tömbbe a literális ui.router hozzáadásával. (Figyeljük meg, hogy a megjegyzés egy későbbi kódrészletben szereplő kód helyőrzőjét jelöli.)

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

A modul definiálása és a függőségek regisztrálása után az alkalmazás egy anonim függvény futtatására van beállítva, amely az alkalmazás konfigurációs fázisában fut le. Itt néhány olyan erőforrást injektálnak a függvénybe, amelyek az UI Router keretrendszer szempontjából relevánsak.

 

A $stateProvider objektum rendelkezik a state metódussal, amely lehetővé teszi az alkalmazás granuláris állapotainak meghatározását, amelyek egybeeshetnek vagy nem egybeeshetnek az URL változásával. A $urlRouterProvider egy olyan objektum, amely lehetővé teszi a böngésző helyének kezelését és megfigyelését. Az UI Router kontextusában a $urlRouterProvider arra szolgál, hogy segítsen meghatározni egy mindenre kiterjedő navigációs forgatókönyvet. Mindegyik objektumot részletesebben tárgyalják a következő kódrészletek. (Ismét megjegyezzük, hogy a következő kódrészletek az előző részletben szereplő helyőrző megjegyzés helyére kerülnek.)

Minden alkalmazásállapotot úgy definiálunk, hogy megadunk egy nevet és megmondjuk a keretrendszernek, hogy hol találja meg a nézet jelölését. Itt a home állapotot úgy definiáljuk, hogy megadjuk az url gyökérhelyét és a templateUrl tulajdonság értékét.

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

Ez azt mondja az alkalmazásnak, hogy töltse be a home.html fájl tartalmát a ui-view helytartóba, amikor a felhasználó az alkalmazás gyökeréhez navigál. Itt kezdjük látni az állapotközpontú útválasztás egyik előnyét. Ha valamilyen oknál fogva azt szeretnénk, hogy a home állapot URL-je a /home-ra mutasson a csupasz gyökérhely (/) helyett, akkor ezt a módosítást csak itt kell elvégezni a konfigurációban. Ez az állapot lemond minden fejlett beállításról, és egy statikus oldalt tölt be a böngészőbe. Máskor is előfordulhat, hogy egy adott vezérlőt szeretne társítani az állapothoz.

A contact állapot úgy van beállítva, hogy a contact.html oldal jelölését töltse be az ui-view helytartóba. Az alapvető csere művelet elvégzésén túl a ContactsController a ui-view utasításnak otthont adó DOM-elem szintjén lehatárolt nézethez is társul.

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

A 3. ábrán látható módon a Kapcsolat oldal tartalmaz egy gombot a Cikkek oldalra való navigáláshoz. A navigáció a ContactsControllerben történik, és bemutatja, hogyan kell egy vezérlőt az UI Router keretrendszer által igény szerint betöltött nézethez kötni.

A cikkek oldal állapota egy lépéssel továbbviszi a konfigurációt azáltal, hogy olyan értékeket ad az objektumhoz, amelyek feloldják az objektumban definiált konfigurált értékeket. Ennek az állapotnak az a célja, hogy megjelenítse az oldalon elérhető cikkek listáját. Ez az állapot úgy van beállítva, hogy a vezérlő számára a cikkinformációk még az instanciázás előtt rendelkezésre álljanak. A következő részletben az állapot definiál egy értéket a resolve objektumban.

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

Az articles tulajdonság ebben az esetben az ArticlesService karakterláncra mutat. Ha egy karakterláncot adunk át értékként a resolve tulajdonságnak, a keretrendszer kapcsolatba lép az azonos néven regisztrált szolgáltatással, és feloldja a szolgáltatást a végső értékig. Ebben az esetben az ArticlesService egy ígéretet ad vissza, így a kapcsolódó vezérlő nem instanciálódik, amíg a szolgáltatás ígérete fel nem oldódik, és a végső objektum nem áll rendelkezésre injektálható értékként a vezérlő számára. Az ArticlesService implementációja a 3. listában érhető el.

Azt követően, hogy a cikkek listája a 4. ábrán látható módon megjelenik a felhasználó számára, a felhasználó kiválaszthat egy cikket, és belemerülhet az oldal tartalmába. Ezt a műveletet egy egymásba ágyazott állapot reprezentálja. Figyeljük meg, hogy az állapot neve egy pontot (.) tartalmaz az articles és az article között, hogy jelezze az állapotok közötti szülő és gyermek kapcsolatot.

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

Itt egy speciális szabály vonatkozik az url tulajdonság kiértékelésére. Mivel ez egy beágyazott nézet (amit az állapotnévben lévő pont jelez), az url tulajdonság értéke a szülő állapot url értékével lesz összekapcsolva. Ez azt jelenti, hogy minden egyező állapot URL címe /articles-rel kezdődik, majd tartalmazza a cikk oldalnevét.

A kettőspont (:) jelenléte URL-paraméterre utal. Azzal, hogy az URL-be paramétert vezetünk be, az állapotdefiníció eléggé rugalmassá válik ahhoz, hogy bármilyen állapotot kezelni tudjon, amely megfelel a szülőállapotával fennálló kapcsolatának. Ez az állapot egy olyan függvényt is tartalmaz, amely a templateUrl értékének visszaadása érdekében fut le. A függvény használata itt lehetőséget ad az állapot url-jében definiált paraméterek használatára. Bármilyen nevet is adunk a paraméternek az url tulajdonságban, az megegyezik a $stateParams objektum tulajdonságnevével. Ezért ez az állapot átveszi az URL-ben átadott pageName-et, hogy a templateUrl függvényben felhasználva elérje az egyes tartalomfájlokat, amelyek végül az ui-view direktívát befogadó elembe kerülnek beillesztésre.

Ez az alkalmazásban definiált utolsó állapot. Az 1. listában láthatjuk, hogyan valósul meg az összes állapot a tényleges inicializálási szkriptben.

Az utolsó parancs, amelyet az alkalmazásnak meg kell adnunk, az, hogy mit tegyen, ha a felhasználó olyan URL-t próbál elérni, amely nincs definiálva a configure metódusban. A $urlRouterProvider objektumból származó otherwise metódus használatával a nem felismert URL-ek elvetésre kerülnek, és az alkalmazást egy alapértelmezett helyre irányítjuk át. Ebben az esetben az alkalmazás úgy van beállítva, hogy a gyökér URL-re irányítsa át az alkalmazást, ha az adott URL nem felel meg egy meghatározott állapotnak.

$urlRouterProvider.otherwise('/');

Most, miután minden alkalmazásállapotot definiáltunk, elkezdhetjük a figyelmünket az ArticlesService felépítésére fordítani.

Adatok feloldása az Articles Service segítségével

A cikk állapotának konfigurációja tartalmazza a resolve opció értékét. Ez az objektum úgy van konfigurálva, hogy az ArticlesService karakterlánc értéke az articles tulajdonsághoz legyen beállítva (lásd az 1. listázást a kontextusért). Egy string megadása a resolve objektumnak utasítja a keretrendszert, hogy keressen meg egy, az alkalmazásban regisztrált szolgáltatást, és oldja fel a szolgáltatást a végső értékéig. Az ArticlesService úgy van implementálva, hogy egy ígéretet adjon vissza.

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

Itt a szolgáltatás a $q szolgáltatást használja egy ígéret létrehozására, hogy egy tömböt adjon vissza. Ebben az esetben az értékek keményen kódoltak, de valós környezetben előfordulhat, hogy egy távoli kiszolgálóhoz kell hozzáférni az adatok megadásához. Mindenesetre a szolgáltatást teljes mértékben fel kell oldani, mielőtt a router keretrendszer átadja a végrehajtást a kapcsolódó vezérlőnek. Ezért a cikk állapotának meghívásakor végül a vezérlőnek függőségként átadják a cikkobjektumok tömbjét.

A feloldott adatok használata az ArticlesControllerben

Az UI Router keretrendszer használatának egyik előnye a gondok elkülönítésének kikényszerítése. Mivel az articles state egy resolve objektumot valósít meg, a cikkek nyers tömbje injektálódik a vezérlőbe.

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

Ez a megközelítés jobb, mintha az ArticlesController-nek “tudnia” kellene az ArticlesService-ről, mert sokkal könnyebb tesztelési célokra egy nyers objektumtömböt mockolni, mint magával a szolgáltatás mockolásával foglalkozni. Az alkalmazás vezérlőinek teljes implementációja a 2. felsorolásban található.

A cikkek listájának megjelenítése

Most, miután az alkalmazás navigált a cikkek állapotához, és a vezérlő a felbontott cikkek tömbjét hatókörbe állította, a nézet már készen áll a megjelenítésre. A Cikkek nézet két részből áll. Az első egy másik div helytartó, amely az ui-view direktívát használja egy beágyazott nézet létrehozásához. A második egy rendezetlen lista az oldalon elérhető különböző cikkekről. A nézet ilyen módon történő felépítése lehetővé teszi a különböző cikkcímekre való kattintást, miközben a cikkek listája az oldalon marad. (Erre egy példát láthat az 5. ábrán.) Ez azért lehetséges, mert az oldal tartalma a cikkszintű ui-nézetbe töltődik be, míg az oldal egésze az alkalmazáshéjban lévő ui-nézetben renderelődik. Az alkalmazáshéj teljes implementációja a 4. listában található.

A következő kódrészlet azt mutatja be, hogy a cikkek nézet hogyan valósít meg egy beágyazott nézetet.

<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>

Ez a jelölés háromféleképpen használja az UI Router keretrendszert. Először is, a div elem a ui-view direktívát használja helytartóként, és ahogy a megjegyzésben is szerepel, átadhatja a helytartóban megjelenítendő alapértelmezett tartalmat, mielőtt a keretrendszer bármilyen tartalmat megjelenítene. Az 5. lista bemutatja, hogy egy statikus üzenetet használunk helyőrző tartalomként az oldalon, mielőtt bármilyen tartalom betöltődne a nézetbe.

Második, az anchor elemre az ui-sref direktívát alkalmazzuk. Ez jelzi az UI Router keretrendszernek, hogy ezt a linket a keretrendszer kontextusában dolgozza fel, és végül egy szabványos href értéket renderel, amely megfelel a deklarált állapot URL-jének az alkalmazás konfigurációjában meghatározott beállítások alapján (lásd az 1. listát).

A keretrendszer harmadik felhasználási módja az, hogy az ui-sref direktíva értéke egy kifejezést fogad el egy beágyazott állapot megfelelő URL-értékének generálására. Itt egy hash kerül átadásra a beágyazott állapot hierarchiájába (ebben az esetben az articles.article), ahol a pageName értékét a bejövő cikk pageName-éhez kötjük. Amikor az UI Router keretrendszer kiértékeli ezt a kifejezést, egy megfelelő URL-értéket generál minden olyan cikkhez, amely megfelel a meghatározott állapotszabályoknak.

Még több absztrakt navigáció

Az utolsó megvalósítandó vezérlő a ContactController, amely az állapot paraméter go metódusát használja az alkalmazás új állapotba navigálására.

app.controller('ContactController', );

Ezzel a go egyszerű meghívásával egy állapotnévvel a kontrollerünk csak azzal foglalkozik, hogy deklarálja az állapotot, amire váltani szeretne, ahelyett, hogy megpróbálná nyomon követni a konkrét útválasztási sémát az alkalmazásban.

Következtetés

Bár az AngularJS egy funkcionális útválasztási implementációval van ellátva, gyorsan felismerhetjük az állapotalapú útválasztási keretrendszer használatának előnyeit a nem triviális alkalmazások esetében. Az UI Router keretrendszer egyszerű módokat biztosít az állapotok definiálására, a függőségek feloldására és az egymásba ágyazott nézetek használatára. Ha még több információt szeretne megtudni arról, hogy mit tud a keretrendszer, mindenképpen látogasson el a projekt otthonába a GitHubon a https://github.com/angular-ui/ui-router/ címen.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.