AngularJS er et JavaScript MVC-rammeverk utviklet av Google, som lar deg bygge godt strukturerte frontend-applikasjoner som er enkle å sjekke og vedlikeholde.
Hvis du ikke har prøvd AngularJS ennå, er det synd. Rammeverket består av et godt integrert sett med verktøy som vil hjelpe deg med å bygge applikasjoner på klientsiden, godt strukturert i et modulsystem, med mindre kode og mer fleksibilitet.
AngularJS utvider HTML, og gir retningslinjer som gir funksjonalitet til fortjenestemarginen din og lar deg lage kraftige dynamiske maler. Du kan også lage dine egne direktiver, lage gjenbrukbare komponenter som fullfører dine behov og abstrakte all logikken for å manipulere DOM.
Den implementerer også toveis datainnbinding, og kobler HTML (visninger) til JavaScript-objekter (modeller) sømløst. Enkelt sagt betyr dette at enhver oppdatering til modellen din umiddelbart vil reflekteres i ditt syn, uten behov for noen DOM-manipulering eller hendelsesbehandling (f.eks. Med jQuery).
Angular tilbyr tjenester på toppen av XHR som i stor grad forenkler koden din og lar deg abstrakte API-anrop til gjenbrukbare tjenester. Med dette kan du flytte forretningsmodellen og logikken din til front-end og bygge uavhengige back-end-webapplikasjoner (agnostiker).Til slutt elsker jeg Angular på grunn av fleksibiliteten når det gjelder serverkommunikasjon. Som de fleste JavaScript MVC-rammer, tillater Angular deg å jobbe med hvilken som helst serverteknologi, så lenge den kan tjene applikasjonen din via en Web REST API. Men Angular tilbyr også andre tjenester enn XHR, noe som i stor grad forenkler koden din og lar deg abstrakte API-anrop til gjenbrukbare tjenester. Som et resultat kan du flytte forretningsmodellen og logikken til front-end og bygge webapplikasjoner baksiden uavhengig. I dette innlegget skal vi gjøre nettopp det: ett trinn av gangen.
Først og fremst skal vi bestemme hvilken applikasjon vi vil bygge. I denne guiden foretrekker vi ikke å bruke for mye tid på bakenden, så vi skal skrive noe om databasen som er lett å få på internett, som en sportsnyhetsapp!
Siden jeg er en stor fan av motorsport og Formel 1, vil jeg bruke en API Autosport-tjeneste som vår back-end. Heldigvis gutta fra Ergast de er snille nok til å tilby et gratis motorsports-API, som er perfekt for oss.
Som en forhåndsvisning av hva vi skal bygge, ta en titt på live demo . For å forskjønne demoen og vise noen vinkelmaler brukte jeg et Bootstrap-tema fra WrapBootstrap , men siden denne artikkelen ikke handler om CSS, skal jeg trekke den fra eksemplene og utelate den helt.
La oss starte eksempelsøknaden med en liten Boilerplate. Jeg anbefaler prosjektet vinkelfrø som det ikke bare gir et flott skjelett for bootstrapping, men legger også grunnlaget for enhetstesting med Karma Y Jasmin (Vi gjør ingen tester i denne demoen, så la oss legge det til side for nå; se Del 2 i denne veiledningen for å lære mer om hvordan du konfigurerer prosjektet ditt, for enhetstesting og ende-til-ende).
REDIGERT (mai 2014): Siden jeg skrev denne veiledningen, prosjektet vinkelfrø har gått gjennom noen store endringer (inkludert tillegg av Bower som pakkeleder). Hvis du har spørsmål om hvordan du implementerer prosjektet, kan du ta en rask titt på den første delen av din referanseguide . I opplæringsdel 2 , Bower, blant annet verktøy, blir forklart mer detaljert.
OK, nå som vi har klonet depotet og installert avhengighetene, kommer applikasjonsskjelettet til å se slik ut:
Nå kan vi begynne å kode. Når vi prøver å bygge en sportsnyhetsapp for et racingmesterskap, la oss starte med den mest relevante visningen: mesterskapsbordet.
Med tanke på at vi allerede har en liste over drivere som er definert innenfor vårt omfang (Bli med meg - Vi kommer dit), og ignorerer CSS (for enklere lesing), kan HTML-en vår være:
Drivers Championship Standings {{$index + 1}}
{{driver.Driver.givenName}} {{driver.Driver.familyName}} {{driver.Constructors[0].name}} {{driver.points}}
Det første du vil legge merke til i denne malen er bruken av uttrykk ('{{' og '}}') for å returnere verdier fra variabler. I AngularJS tillater uttrykk deg å utføre noen beregninger for å returnere en ønsket verdi. Noen gyldige uttrykk vil være:
{{ 1 + 1 }}
{ date }
{{ user.name }}
Uttrykk er faktisk JavaScript-lignende utdrag. Til tross for at du er veldig kraftig, bør du ikke bruke uttrykk for å implementere noen høyere nivålogikk. For å gjøre dette bruker vi retningslinjer.
Den andre tingen du vil legge merke til er tilstedeværelsen av ng-attributter, som du ikke vil se i typisk markering. Det er retningslinjene.
På et høyt nivå er direktiver plassholdere (som generiske navn, koder og attributter) som instruerer AngularJS om å feste en gitt oppførsel til et DOM-element (eller transformere det, erstatte det osv.). La oss ta en titt på de vi allerede har sett:
Direktivet ng-app
Det er ansvarlig for å starte programmet, for å definere omfanget. I AngularJS kan du ha flere applikasjoner på samme side, så denne retningslinjen definerer hvor hver applikasjon begynner og slutter.
Direktivet ng-controller
definere hvilken kontroller som skal stå for visningen din. I dette tilfellet betegner vi det driversController
, som vil gi vår liste over ledere (driversList
).
Direktivet ng-repeat
Det er en av de mest brukte, og det brukes til å definere malområdet når du går gjennom samlinger. I eksemplet ovenfor gjentar du en linje i tabellen for hver leder i driversList
.
Selvfølgelig er vårt syn ubrukelig uten en kontroller. La oss legge til driversController i controllers.js
:
angular.module('F1FeederApp.controllers', []). controller('driversController', function($scope) { $scope.driversList = [ { Driver: { givenName: 'Sebastian', familyName: 'Vettel' }, points: 322, nationality: 'German', Constructors: [ {name: 'Red Bull'} ] }, { Driver: { givenName: 'Fernando', familyName: 'Alonso' }, points: 207, nationality: 'Spanish', Constructors: [ {name: 'Ferrari'} ] } ]; });
Du har sannsynligvis lagt merke til $ scope-variabelen som vi sender som en parameter til kontrolleren. Variabelen $scope
det er ment å binde kontrolleren din og visninger. Spesielt bærer den alle dataene som skal brukes i malen. Alt som legges til det (som driversList
i forrige eksempel) vil være direkte tilgjengelig i dine synspunkter. Foreløpig skal vi jobbe med en rekke dummy-data (statisk), som vi senere skal erstatte med API-tjenesten vår.
Nå, legg dette til app.js:
angular.module('F1FeederApp', [ 'F1FeederApp.controllers' ]);
Med denne kodelinjen initialiserer vi applikasjonen vår og registrerer modulene det avhenger av. Vi kommer tilbake til den filen (app.js
) senere.
La oss nå sette alt sammen i index.html
:
F-1 Feeder Drivers Championship Standings {{$index + 1}}
{{driver.Driver.givenName}} {{driver.Driver.familyName}} {{driver.Constructors[0].name}} {{driver.points}}
Modulerte mindre feil, nå kan du starte appen din og sjekke (statisk) listen over drivere.
Merk: Hvis du trenger hjelp til å feilsøke applikasjonen din og se på modellene dine og søke i nettleseren, anbefaler jeg å ta en titt på den imponerende batarangen; plugin for Chrome.
Siden vi allerede vet hvordan vi viser kontrollerdataene etter vårt syn, er det på tide å hente inn live data fra en RESTful-server.
For å lette kommunikasjonen med HTTP-servere, tilbyr AngularJS tjenestene $http
og $resource
. Den første er et lag på toppen av XMLHttpRequest eller JSONP , mens sistnevnte gir et høyere abstraksjonsnivå. Vi skal bruke $http
.
For å abstrakte våre samtaler til server-API fra kontrolleren, skal vi lage vår egen tilpassede tjeneste, som vil fange opp dataene og fungere som en wrapper rundt $http
ved å legge den til vår services.js
:
angular.module('F1FeederApp.services', []). factory('ergastAPIservice', function($http) { var ergastAPI = {}; ergastAPI.getDrivers = function() { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK' }); } return ergastAPI; });
Med de to første linjene oppretter vi en ny modul (F1FeederApp.services
) og registrerer en tjeneste innenfor den modulen (F1FeederApp.services
). Merk at vi sender $ http som en parameter til den tjenesten. Dette forteller motoren avhengighetsinjeksjon fra Angular, som vår nye tjeneste krever ( eller det kommer an på ) av tjenesten $http
.
På en lignende måte må vi fortelle Angular å inkludere den nye modulen vår i applikasjonen. La oss registrere det med app.js
, og erstatte vår eksisterende kode med:
angular.module('F1FeederApp', [ 'F1FeederApp.controllers', 'F1FeederApp.services' ]);
Nå er alt vi trenger å gjøre å justere controller.js
litt, integrer ergastAPIservice
som en avhengighet, og vi er klare til å fortsette:
angular.module('F1FeederApp.controllers', []). controller('driversController', function($scope, ergastAPIservice) { $scope.nameFilter = null; $scope.driversList = []; ergastAPIservice.getDrivers().success(function (response) { //Dig into the responde to get the relevant data $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings; }); });
Last nå på nytt programmet og sjekk resultatet. Legg merke til at vi ikke gjorde noen endringer i malen vår, men vi la til en variabel nameFilter
på vår rekkevidde. Vi skal bruke denne variabelen.
Flott! Vi har en funksjonell kontroller. Men det viser bare en liste over drivere. Vi kommer til å legge til noen funksjoner gjennom en enkel tekstsøking, som vil filtrere listen. La oss legge til følgende linje i index.html
, rett under etiketten:
ng-model
Nå bruker vi direktivet Denne linjen forteller På dette tidspunktet kommer den toveis databindingen inn: hver gang en verdi angis i oppslagsfeltet, sørger Angular umiddelbart for at Oppdater appen og se på søkefeltet. Merk at dette filteret vil søke etter nøkkelordet i alle attributtene til modellen, inkludert de vi ikke bruker. La oss si at vi bare vil filtrere Nå, tilbake til index.html, oppdaterer vi linjen som inneholder direktivet Oppdater appen en gang til, og nå har vi et søk etter navn. Vårt neste mål er å opprette en førerdataside, som lar oss klikke på hver fører og se løpsinformasjonen deres. Først skal vi inkludere tjenesten Med denne endringen, navigering til AngularJS lar deg binde rutene dine til spesifikke kontrollere og visninger. Men først må vi fortelle Angular hvor disse delvise synspunktene skal gjengis. For å gjøre dette bruker vi direktivet Nå når vi navigerer gjennom applikasjonsstiene, vil Angular laste den tilhørende visningen og gjengi den i stedet for etiketten. Alt vi trenger å gjøre er å opprette en fil med navnet Til slutt skal vi bestemme hva vi vil vise på informasjonssiden. Hva med et sammendrag av alle relevante fakta om sjåføren (f.eks. Fødselsdato, nasjonalitet), sammen med en tabell som inneholder de siste resultatene dine? For å gjøre det legger vi til følgende i Denne gangen gir vi driver-ID til tjenesten slik at vi kan hente relevant informasjon for en bestemt driver. Nå endrer vi Det viktige å merke seg her er at vi bare injiserer tjenesten Nå som vi har dataene våre i omfang, trenger vi bare den gjenværende delvisningen. La oss lage en fil med navnet Legg merke til at vi nå bruker direktivet Legg til en haug med CSS og gjengi siden din. Du bør ende opp med noe sånt som dette: Du er nå klar til å starte applikasjonen og sørge for at begge rutene fungerer som ønsket. Du kan også legge til en statisk meny i REDIGERT (mai 2014): Jeg har mottatt mange forespørsler om en nedlastbar versjon av koden vi bygde i denne veiledningen. Derfor har jeg bestemt meg for å gjøre den tilgjengelig her (fratatt CSS). Sannheten er imidlertid at jeg ikke anbefaler å laste den ned, siden denne guiden inneholder hvert trinn du trenger for å generere den samme applikasjonen med egne hender, noe som vil være en mye mer nyttig og effektiv læringsøvelse. På dette punktet i opplæringen har vi dekket alt du trenger for å skrive en enkel applikasjon (for eksempel en Formel 1-informator). Hver av de gjenværende sidene i live-demoen (f.eks. Constructors 'Championship-tabell, lagdetaljer, tidsplan) har samme grunnleggende struktur og konsepter som vi har gjennomgått. Til slutt, husk at Angular er et veldig kraftig rammeverk, og vi har knapt skrapet overflaten når det gjelder alt den har å tilby. I del 2 Fra denne opplæringen skal vi gi eksempler på hvorfor Angular skiller seg ut blant sine jevnaldrende i front-end MVC-rammer: testbarhet. La oss gjennomgå prosessen med å skrive og kjøre enhetstester med Karma , oppnå kontinuerlig integrasjon med Kvinner , Bakke , Y Bower og andre styrker i dette fantastiske front-end-rammeverket.$scope.nameFilter
. Dette direktivet binder tekstfeltet vårt til variabelen index.html
og sørger for at verdien alltid er oppdatert med inngangsverdien. La oss nå besøke ng-repeat
en gang til, og la oss gjøre en liten justering av linjen som inneholder direktivet : ng-repeat
driversList
at matrisen nameFilter
før dataene sendes ut må filtreres etter verdien som er lagret i $scope.nameFilter
.nameFilter
som vi forbinder med det er oppdatert med den nye verdien. Siden binding fungerer begge veier, i det øyeblikket verdien ng-repeat
blir oppdatert, den andre lederen som er tilknyttet den (det vil si Driver.givenName
) mottar også den nye verdien, og visningen blir umiddelbart oppdatert.Driver.familyName
og driversController
: Først legger vi til $scope.driversList =[];
, rett under linjen $scope.searchFilter = function (driver) ;
:ng-repeat
: $routeProvider
Ruter
app.js
(no app.js
) som vil hjelpe oss med å håndtere disse forskjellige applikasjonsstiene. Deretter vil vi legge til to av disse rutene: en for mesterskapstabellen og en for førerdata. Her er vår nye angular.module('F1FeederApp', [ 'F1FeederApp.services', 'F1FeederApp.controllers', 'ngRoute' ]). config(['$routeProvider', function($routeProvider) { $routeProvider. when('/drivers', {templateUrl: 'partials/drivers.html', controller: 'driversController'}). when('/drivers/:id', {templateUrl: 'partials/driver.html', controller: 'driverController'}). otherwise({redirectTo: '/drivers'}); }]);
:http://domain/#/drivers
driversController
vil laste inn partials/drivers.html
og vil finne den delvisningen som skal gjengis i ng-view
. Men vent! Vi har ikke noen delvise visninger ennå, ikke sant? Vi blir nødt til å lage dem også.Delvis utsikt
index.html
, og endrer vårt F-1 Feeder
for å gjenspeile følgende:partials/drivers.html
, og legge HTML-mesterskapstabellen vår der. Vi kommer også til å bruke denne muligheten til å knytte førerens navn til ruten vår fra førerinformasjonen:
Drivers Championship Standings {{$index + 1}} {{driver.Driver.givenName}} {{driver.Driver.familyName}}
{{driver.Constructors[0].name}} {{driver.points}} services.js
angular.module('F1FeederApp.services', []) .factory('ergastAPIservice', function($http) { var ergastAPI = {}; ergastAPI.getDrivers = function() { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK' }); } ergastAPI.getDriverDetails = function(id) { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/driverStandings.json?callback=JSON_CALLBACK' }); } ergastAPI.getDriverRaces = function(id) { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/results.json?callback=JSON_CALLBACK' }); } return ergastAPI; });
:controllers.js
angular.module('F1FeederApp.controllers', []). /* Drivers controller */ controller('driversController', function($scope, ergastAPIservice) { $scope.nameFilter = null; $scope.driversList = []; $scope.searchFilter = function (driver) ; ergastAPIservice.getDrivers().success(function (response) { //Digging into the response to get the relevant data $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings; }); }). /* Driver controller */ controller('driverController', function($scope, $routeParams, ergastAPIservice) { $scope.id = $routeParams.id; $scope.races = []; $scope.driver = null; ergastAPIservice.getDriverDetails($scope.id).success(function (response) { $scope.driver = response.MRData.StandingsTable.StandingsLists[0].DriverStandings[0]; }); ergastAPIservice.getDriverRaces($scope.id).success(function (response) { $scope.races = response.MRData.RaceTable.Races; }); });
:$routeParams
$routeParams.id
på førerens kontroller. Denne tjenesten lar oss få tilgang til URL-parameterne våre (for: id, i dette tilfellet) ved hjelp av partials/driver.html
. <- Back to drivers list
og vi legger til:
{{driver.Driver.givenName}} {{driver.Driver.familyName}} Country: {{driver.Driver.nationality}}
Team: {{driver.Constructors[0].name}}
Birth: {{driver.Driver.dateOfBirth}}
Biography
Formula 1 2013 Results Round Grand Prix Team Grid Race {{race.round}} {{race.raceName}}
{{race.Results[0].Constructor.name}} {{race.Results[0].grid}} {{race.Results[0].position}} ng-show
true
til god bruk. Dette direktivet viser bare HTML-elementet hvis det medfølgende uttrykket er false
(det vil si verken null
eller index.html
). I dette tilfellet vil avataren bare vises når driverobjektet er lastet inn i omfang, av kontrolleren.Siste grep
|_+_|
, for å forbedre brukerens navigasjonsegenskaper. Mulighetene er endeløse. konklusjon