Eenvoudiger AngularJS Routing met Angular UI Router

Hoewel AngularJS voorzien is van ingebouwde routing, kan het soms beperkend zijn; het Angular UI Router framework kan helpen de pijn te verzachten. De native AngularJS routing implementatie is verantwoordelijk voor het initialiseren van controllers die overeenkomen met applicatie-routes. Hoewel deze functionaliteit goed werkt in basisscenario’s, in geavanceerde situaties, vindt u al snel dat Angular’s native routing:

  • Verplicht u om handmatig URL’s strings te wijzigen in uw hele code base wanneer een URL verandert.
  • Verplicht u om de route syntaxis verbatim te onthouden om te navigeren naar een pagina.
  • biedt geen geneste views.
  • biedt geen benoemde views.
  • Mag u niet toestaan om gegevens door te geven tijdens navigatie.

Als alternatief is het Angular UI Router framework een abstractielaag voor routing die een meer declaratieve benadering van navigatie biedt. De UI Router framework vult ook een aantal van de gaten van de native implementatie door het verstrekken van geneste en benoemde views, kunt u gegevens doorgeven tussen de standpunten, en nog veel meer.

Het Angular UI Router-framework is een abstractielaag voor routing met een declaratieve benadering van navigatie

In dit artikel leer je een eenvoudige applicatie te bouwen die gebruikmaakt van het UI Router-framework. Gaandeweg raakt u vertrouwd met states, hoe afhankelijkheden op te lossen, en leert u verschillende methoden voor navigatie.

States begrijpen

De beste manier om het probleem te begrijpen dat het UI Router framework hoopt op te lossen is misschien door de aard van het Web te beschouwen. In de meeste toepassingen definieer je een expliciet URL-pad wanneer je een link naar een pagina maakt. Bijvoorbeeld, als u wilt navigeren naar de Producten pagina van uw site, dan zou u een URL kunnen hebben als:

Code Sample 1: Version 2 Flexible Container

http://www.example.com/products

Er zijn twee problemen met deze situatie. Het eerste is dat u het exacte letterlijke pad naar de Producten-pagina moet onthouden telkens wanneer u een link maakt. Hoewel het hier gegeven voorbeeld gemakkelijk te onthouden is, zijn veel URL’s in de echte wereld niet zo gemakkelijk te onthouden. Het volgende probleem doet zich voor wanneer het onvermijdelijke gebeurt en iemand besluit het pad te veranderen in iets anders. Wanneer een URL verandert, dan moet je ervoor zorgen dat alle bestaande links worden bijgewerkt om naar de nieuwe locatie te verwijzen.

In plaats van het woordelijk bijhouden van de URL paden, zou je niet liever gewoon de applicatie vertellen om “naar de Producten pagina te gaan”? Door de applicatie zich te laten bezighouden met de navigatie, bent u verlost van de noodzaak om het letterlijke pad te kennen en bent u beschermd tegen gebroken links veroorzaakt door de onvermijdelijkheid van verandering. Het gebruik van toestanden geeft je dit niveau van flexibiliteit. Een state bevat een URL-locatie, de naam van de state, gespecialiseerde gegevens voor de view, een manier om de view te lokaliseren of te genereren, en kan zelfs aangepaste events genereren.

Inleiding tot Angular UI Router

Angular UI Router is een framework dat de native routing in AngularJS volledig vervangt. De UI Router is zeer vergelijkbaar met de native AngularJS routing in die zin dat toepassingen zijn samengesteld uit een schil die een placeholder voor dynamische inhoud bevat. Figuur 1 laat zien hoe de applicatie shell een element host dat gebruik maakt van de ui-view directive. Wanneer toestandsregels in het framework worden geëvalueerd, wordt HTML-inhoud in de plaatshouder weergegeven.

Figure 1: Het UI Router-framework voegt HTML-inhoud toe aan een plaatshouder op de pagina.

Angular UI Router is een framework dat de native routing die beschikbaar is in AngularJS, volledig vervangt.

Naast het renderen van HTML-inhoud ondersteunt het UI Router-framework URL-routering, de mogelijkheid om afhankelijkheden op te lossen voordat controllers worden geïnitialiseerd, benoemde en geneste weergaven, utiliteitsfilters, toestandsveranderingsgebeurtenissen en declaratieve overgangen tussen toestanden.

Navigeren tussen toestanden

Er zijn een paar verschillende manieren die je kunt gebruiken om tussen verschillende toestanden te bewegen. De eerste manier is de ui-sref directive. Je bent waarschijnlijk bekend met het href attribuut van de HTML anchor tag (die een hypertext referentie voorstelt); op dezelfde manier verwijst de ui-sref directive naar een toestandsreferentie. Je gebruikt de directive door een state naam te declareren met de ui-sref directive toegepast op een anker. Bijvoorbeeld:

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

Als het UI Router framework deze directive evalueert, wordt het anker getransformeerd om de juiste URL waarde te krijgen. Bijvoorbeeld:

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

Merk op dat het element wordt bijgewerkt om een href attribuut te bevatten met een waarde die overeenkomt met hoe de URL moet worden bijgewerkt om naar de Over ons pagina te navigeren. De ui-sref directive is vrij flexibel. Het ondersteunt eenvoudige scenario’s, maar ook manieren om te gaan met geneste staten en zelfs geparametriseerde waarden.

De volgende benadering voor het navigeren tussen staten is het gebruik van een methode van het $state object dat beschikbaar is voor een Angular controller. In deze volgende snippet kun je zien hoe de navigate methode is geïmplementeerd om $state.go aan te roepen en de applicatie over te laten gaan naar de about state.

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

Het $state object wordt geïnjecteerd door het UI Router framework en bevat een aantal methoden om je te helpen bij het beheren en manipuleren van state in de applicatie. De waarde hiervan is dat je de applicatie vertelt om “naar” de about state te gaan en je bent bevrijd van het kennen van het letterlijke URL-pad naar de pagina.

Downloaden en installeren

Er zijn een aantal verschillende manieren waarop je toegang kunt krijgen tot het UI Router framework. U kunt de laatste versie direct downloaden van de GitHub repository op https://github.com/angular-ui/ui-router. U kunt het framework ook installeren via Bower of NuGet of zelfs CDN links in uw pagina’s opnemen; beide zijn beschikbaar op http://cdnjs.com/libraries/angular-ui-router.

Angular UI Router gebruiken

Wat volgt is een tutorial die demonstreert hoe u een eenvoudige statische content-gebaseerde applicatie kunt bouwen met behulp van het UI Router framework. Figuur 2 toont het voorbeeld van de home page applicatie die u leert te bouwen tijdens het lezen van dit artikel. In deze schermafbeelding kunt u zien hoe de applicatie is opgebouwd en hoe de inhoud van de home page in de placeholder wordt geïnjecteerd met behulp van de ui-view directive.

Figuur 2 : De startpagina en de standaardtoestand van de toepassing

U kunt van toestand veranderen om naar de contactpagina te navigeren, zoals te zien is in figuur 3. Het mechanisme op de contactpagina maakt gebruik van de go-methode van het object $state door een statusnaam aan de methode door te geven.

Figure 3 : De contactpagina

De volgende status is gekoppeld aan de lijstpagina van het artikel, zoals te zien is in Figuur 4. Hier wordt een array met artikelgegevens beschikbaar gemaakt voor de view nadat de ruwe waarden door het UI Framework in de controller zijn geïnjecteerd. Navigatie op deze pagina wordt vergemakkelijkt door de ui-sref directive die het mogelijk maakt om declaratief de applicatiestatus uit te drukken waarnaar u wilt navigeren.

Fig ure 4 : De artikelenlijstpagina

De laatste pagina, te zien in Figuur 5, laat zien hoe een geneste status wordt gebruikt in de applicatie.

Figuur 5 : De pagina met artikeldetails

Configuratie

Om met het UI Router framework te kunnen gaan werken, moet u de pagina configureren. De eerste stap is het toevoegen van de naam van de applicatie in het ng-app attribuut van het HTML element op de pagina. Hier is de naam van de applicatie eenvoudigweg app.

< html ng-app="app">

Volgende stap is het toevoegen van de ui-view directive aan een element op de pagina om te fungeren als plaatshouder voor inhoud die door het framework wordt geïnjecteerd. In dit geval wordt de directive toegevoegd aan een div element.

< div ui-view></div>

Ten slotte moet u zowel Angular als Angular UI Router verwijzen op de pagina.

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

Deze code snippet bevat ook een verwijzing naar het app.js script in de script/app folder die de code bevat om de Angular applicatie te initialiseren. Het initialisatie proces is waar het grootste deel van de setup en de interface met het UI Router framework is geïmplementeerd.

States definiëren

Zoals eerder gezegd, is de basis van het UI Router raamwerk het gebruik van verschillende states in een applicatie. Door toegang te krijgen tot elk van deze toestanden, kan de toepassing navigeren naar of zichzelf opnieuw samenstellen naar omstandigheden binnen de levenscyclus van de toepassing. De volgende sectie demonstreert hoe de toestanden voor de toepassing te definiëren; alle van de code is geïmplementeerd in het bestand app.js. Elke sectie wordt afzonderlijk bekeken, maar als u het volledige initialisatie-script wilt zien, raadpleeg dan Listing 1.

De eerste stap is het configureren van UI Router in uw AngularJS applicatie. Na het benoemen van de module, heeft u de mogelijkheid om het UI Router framework te registreren als een dependency van de applicatie door de letterlijke ui.router toe te voegen aan de dependencies array. (Merk op hoe de opmerking een placeholder voor code in een volgende snippet aangeeft.)

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

Zodra de module is gedefinieerd en de afhankelijkheden zijn geregistreerd, wordt de toepassing ingesteld om een anonieme functie uit te voeren die wordt uitgevoerd tijdens de configuratiefase van de toepassing. Hier zijn er een paar middelen geïnjecteerd in de functie die relevant zijn voor het UI Router framework.

 

Het $stateProvider object bevat de state methode waarmee je granulaire applicatie toestanden kunt definiëren die al dan niet kunnen samenvallen met veranderingen in de URL. De $urlRouterProvider is een object dat je controle geeft over hoe de browser’s locatie wordt beheerd en waargenomen. In de context van de UI Router, wordt $urlRouterProvider gebruikt om een catch-all navigatie scenario te definiëren. Elk van deze objecten wordt in meer detail besproken in de volgende codefragmenten. (Nogmaals, merk op dat de volgende code snippets worden geplaatst op de positie van de placeholder commentaar in de vorige snippet.)

Elke applicatie toestand wordt gedefinieerd door het verstrekken van een naam en het vertellen van het kader waar de markup voor de weergave te vinden. Hier wordt de home-status gedefinieerd door de root-locatie op te geven voor de url en een waarde voor de templateUrl eigenschap.

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

Dit vertelt de applicatie om de inhoud van het home.html bestand in de ui-view plaatshouder te laden wanneer de gebruiker navigeert naar de root van de applicatie. Hier begin je een van de voordelen van state-centric routing te zien. Als je, om wat voor reden dan ook, de URL voor de home status naar /home zou willen laten wijzen in plaats van naar de kale root locatie (/), dan zou die verandering alleen hier in de configuratie hoeven plaats te vinden. Deze toestand gaat voorbij aan elke geavanceerde instelling en laadt een statische pagina in de browser. Er kunnen andere momenten zijn waarop je een specifieke controller aan de toestand wilt koppelen.

De contact toestand is ingesteld om de opmaak van de contact.html pagina in de ui-view plaatshouder te laden. Naast het uitvoeren van een basis vervangende operatie, is de ContactsController ook gekoppeld aan de view scoped op het niveau van het DOM-element dat de ui-view directive host.

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

Zoals te zien in figuur 3, de Contact pagina bevat een knop om te navigeren naar de artikelen pagina. De navigatie vindt plaats in de ContactsController en demonstreert hoe je een controller kunt koppelen aan een view die op verzoek wordt geladen door het UI Router framework.

De toestand van de Artikel-pagina gaat een stap verder in de configuratie door waarden toe te voegen aan het object dat alle geconfigureerde waarden in het object omzet. Het doel van deze status is om een lijst van de beschikbare artikelen op de site weer te geven. Deze toestand is zo ingesteld dat de artikel informatie beschikbaar is voor de controller voordat deze wordt instantiëerd. In de volgende snippet definieert de toestand een waarde in het object resolve.

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

In dit geval wijst de eigenschap articles naar de string ArticlesService. Wanneer je een string als waarde aan de resolve eigenschap doorgeeft, neemt het framework contact op met een service die onder dezelfde naam is geregistreerd en resolvet de service naar de uiteindelijke waarde. In dit geval retourneert de ArticlesService een belofte zodat de geassocieerde controller niet wordt geïnitialiseerd totdat de belofte van de service is opgelost en het uiteindelijke object beschikbaar is als een injecteerbare waarde voor de controller. De implementatie van de ArticlesService is te vinden in Listing 3.

Nadat de lijst met artikelen aan de gebruiker is getoond, zoals te zien is in Figuur 4, kan de gebruiker een artikel selecteren en in de inhoud van de site duiken. Deze actie wordt voorgesteld door een geneste toestand. Merk op dat de state naam een punt (.) bevat tussen articles en article om een ouder en kind relatie aan te geven tussen de states.

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

Hier is een speciale regel toegepast op hoe de url eigenschap wordt geëvalueerd. Omdat dit een geneste view is (zoals aangegeven door de punt in de state naam) zal de waarde van de url eigenschap worden samengevoegd met de bovenliggende state’s url waarde. Dit betekent dat alle overeenkomende toestanden een URL zullen hebben die begint met /articles en dan de pagina naam van het artikel bevat.

De aanwezigheid van de dubbele punt (:) is een indicatie voor een URL parameter. Door een parameter in de URL te introduceren, wordt de toestandsdefinitie flexibel genoeg om elke toestand aan te kunnen die overeenkomt met de relatie die het heeft met zijn bovenliggende toestand. Deze toestand bevat ook een functie die wordt uitgevoerd om de waarde voor templateUrl terug te geven. Het gebruik van een functie hier geeft je de mogelijkheid om de parameters te gebruiken die gedefinieerd zijn in de url van de state. De naam die je aan de parameter geeft in de url eigenschap komt overeen met de property naam van het $stateParams object. Daarom neemt deze staat de pageName die in de URL wordt doorgegeven om te gebruiken in de templateUrl functie om toegang te krijgen tot individuele inhoudsbestanden die uiteindelijk worden geïnjecteerd in het element dat de ui-view directive host.

Dit is de laatste staat die in de applicatie is gedefinieerd. Om te zien hoe alle toestanden zijn geïmplementeerd in het eigenlijke initialisatie script, zie Listing 1.

De laatste opdracht die aan de applicatie moet worden gegeven, is wat er moet gebeuren als de gebruiker een URL probeert te benaderen die niet in de configure-methode is gedefinieerd. Door gebruik te maken van de otherwise methode van het $urlRouterProvider object, worden alle niet-herkende URL’s genegeerd en wordt de applicatie omgeleid naar een standaard locatie. In dit geval wordt de toepassing geconfigureerd om door te verwijzen naar de root URL als de gegeven URL niet overeenkomt met een gedefinieerde toestand.

$urlRouterProvider.otherwise('/');

Nu, met elke toestand van de toepassing gedefinieerd, kunt u beginnen met uw aandacht te richten op het bouwen van de ArticlesService.

Resolving Data with the Articles Service

De configuratie voor de toestand van het artikel omvat een waarde voor de resolve optie. Dit object is geconfigureerd om een string waarde van ArticlesService ingesteld te hebben op de articles eigenschap (zie Listing 1 voor context). Het leveren van een string aan het resolve object vertelt het framework om een service te vinden die geregistreerd is in de applicatie en om de service op te lossen naar zijn uiteindelijke waarde. De ArticlesService is geïmplementeerd om een belofte te retourneren.

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

Hier gebruikt de service $q om een belofte te maken om een array te retourneren. In dit geval zijn de waarden hard gecodeerd, maar in een real-world context kan het nodig zijn een externe server te benaderen om de gegevens te verstrekken. In ieder geval moet de service volledig zijn opgelost voordat het router framework de uitvoering doorgeeft aan de bijbehorende controller. Daarom, als de artikel status wordt aangeroepen, wordt uiteindelijk de controller een array van artikel objecten doorgegeven als een dependency.

Gebruik van Resolved Data in de ArticlesController

Eén van de voordelen van het gebruik van het UI Router framework is de mogelijkheid om scheiding van belangen af te dwingen. Omdat de articles state een resolve object implementeert, wordt de ruwe array van artikelen in de controller geïnjecteerd.

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

Deze aanpak is superieur aan de eis dat de ArticlesController “weet” van de ArticlesService, omdat het veel gemakkelijker is om een ruwe array van objecten te mocken voor testdoeleinden in plaats van de service zelf te mocken. De volledige implementatie voor de controllers van de applicatie is te vinden in Listing 2.

Rendering van de Artikelen Lijst

Nu de applicatie naar de status van het artikel heeft genavigeerd en de controller de opgeloste artikelen array in scope heeft, is de view nu klaar om gerenderd te worden. De Articles view bestaat uit twee delen. Het eerste is een andere div plaatshouder die de ui-view richtlijn gebruikt om een geneste view te maken. Het tweede deel is een ongeordende lijst van de verschillende artikelen die op de site beschikbaar zijn. Door de view zo te construeren, kun je op verschillende artikeltitels klikken terwijl de lijst van artikelen op de pagina blijft staan. (Een voorbeeld hiervan is te zien in Figuur 5.) Dit is mogelijk omdat de inhoud van de pagina wordt geladen in de artikel-niveau ui-view terwijl de pagina als geheel wordt gerenderd in de ui-view in de applicatieschil. De volledige implementatie van de applicatieschil is te vinden in Listing 4.

Het volgende codefragment laat zien hoe de artikelenview een geneste view implementeert.

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

Er zijn drie manieren waarop deze markup gebruikmaakt van het UI Router-framework. Ten eerste gebruikt het div element de ui-view directief als een plaatshouder, en, zoals het commentaar aangeeft, kun je standaard inhoud doorgeven om in de plaatshouder te renderen voordat enige inhoud wordt gerenderd door het framework. Listing 5 demonstreert hoe een statisch bericht wordt gebruikt als plaatshouder op de pagina voordat enige inhoud in de view wordt geladen.

Ten tweede, het anker element heeft de ui-sref directive toegepast. Dit geeft een signaal aan het UI Router framework om deze link in de context van het framework te verwerken en uiteindelijk een standaard href waarde te renderen die overeenkomt met de URL voor de gedeclareerde status op basis van de instellingen die zijn gedefinieerd in de applicatieconfiguratie (zie Listing 1).

De derde manier waarop het framework wordt gebruikt is dat de waarde van de ui-sref directive een expressie accepteert om de juiste URL waarde voor een geneste state te genereren. Hier wordt een hash doorgegeven aan de geneste state hiërarchie (in dit geval articles.article) waar de waarde voor pageName wordt gebonden aan de pageName van het binnenkomende artikel. Wanneer het UI Router framework deze expressie evalueert, wordt een corresponderende URL waarde gegenereerd voor elk artikel dat overeenkomt met de gedefinieerde state regels.

More Abstract Navigation

De laatste controller om te implementeren is de ContactController, die gebruik maakt van de state parameter’s go methode om de applicatie naar een nieuwe state te navigeren.

app.controller('ContactController', );

Hier, door eenvoudigweg go aan te roepen met een state naam, is je controller alleen bezig met het verklaren van de state waarnaar je wilt veranderen in plaats van te proberen het concrete routing schema in de applicatie bij te houden.

Conclusie

Hoewel AngularJS wordt geleverd met een functionele routing implementatie, kun je snel de voordelen realiseren van het gebruik van een state-based routing framework voor niet-triviale applicaties. Het UI Router framework biedt eenvoudige manieren om toestanden te definiëren, afhankelijkheden op te lossen, en gebruik te maken van geneste views. Voor nog meer informatie over wat het framework kan doen, kun je terecht op GitHub op https://github.com/angular-ui/ui-router/.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.