Koska nykyaikaiset verkkosovellukset tekevät yhä enemmän asiakaspuolella (tosiasia, että me kutsumme niitä nyt 'verkkosovelluksiksi' eikä 'verkkosivustoiksi', on melko kertova), on kasvanut kiinnostus asiakaspuolen kehyksiä kohtaan . Tällä alalla on paljon pelaajia, mutta sovelluksissa, joissa on paljon toiminnallisuutta ja paljon liikkuvia osia, kaksi niistä erottuu erityisesti: Angular.js ja Ember.js .
Olemme jo julkaisseet kattavan [Angular.js-opetusohjelman] [https://www.toptal.com/angular-js/a-step-by-step-guide-to-your-first-angularjs-app], joten keskitymme Ember.js: ään tässä viestissä, johon rakennamme yksinkertaisen Ember-sovelluksen musiikkikokoelmasi luettelointiin. Sinulle esitellään kehyksen tärkeimmät rakennuspalikat ja saat vilauksen sen suunnitteluperiaatteista. Jos haluat nähdä lähdekoodin lukemisen aikana, se on saatavana nimellä rock-and-roll Githubissa .
Näin Rock & Roll -sovelluksemme näyttää lopullisessa versiossaan:
Vasemmalla näet, että meillä on luettelo artisteista ja oikealla luettelo valitun artistin kappaleista (voit myös nähdä, että minulla on hyvä musiikkimaku, mutta poikkeaen). Uusia artisteja ja kappaleita voidaan lisätä yksinkertaisesti kirjoittamalla tekstikenttään ja painamalla viereistä painiketta. Kunkin kappaleen vieressä olevat tähdet palvelevat sen arviointia, à la iTunes.
Voisimme jakaa sovelluksen alkeelliset toiminnot seuraaviin vaiheisiin:
Meillä on vielä pitkä matka, jotta tämä toimisi, joten aloitetaan.
Yksi Emberin erityispiirteistä on URL-osoitteiden painottaminen. Monissa muissa kehyksissä erillisten URL-osoitteiden käyttäminen erillisille näytöille joko puuttuu tai siihen puututaan jälkikäteen. Emberissä reititin - komponentti, joka hallitsee URL-osoitteita ja niiden välisiä siirtymiä - on keskeinen osa, joka koordinoi rakennuspalikoiden välistä työtä. Näin ollen se on myös avain ihmisten sovellusten sisäisen toiminnan ymmärtämiseen.
Tässä ovat sovelluksemme reitit:
App.Router.map(function() { this.resource('artists', function() { this.route('songs', { path: ':slug' }); }); });
Määritämme resurssireitin, artists
ja a songs
reitti sisäkkäin sen sisällä. Tämä määritelmä antaa meille seuraavat reitit:
Käytin upeaa Ember Inspector -laajennusta (se on olemassa molemmille Kromi ja Firefox ) näyttääksesi luodut reitit helposti luettavalla tavalla. Tässä ovat Ember-reittien perussäännöt, jotka voit tarkistaa tapauskohtaisesti yllä olevan taulukon avulla:
On olemassa implisiittinen application
reitti.
Tämä aktivoidaan kaikki pyynnöt (siirtymät).
On olemassa implisiittinen index
reitti.
Tämä syötetään, kun käyttäjä siirtyy sovelluksen päähakemistoon.
Jokainen resurssireitti luo reitin samalla nimellä ja luo implisiittisesti hakemistoreitin sen alle.
Tämä hakemistoreitti aktivoituu, kun käyttäjä navigoi reitille. Meidän tapauksessamme artists.index
käynnistyy, kun käyttäjä siirtyy kohtaan /artists
Yksinkertaisen (ei-resurssisen) sisäkkäisen reitin etuliitteenä on pääreitin nimi.
Määrittelemämme reitin this.route('songs', ...)
on artists.songs
sen nimenä. Se laukaistaan, kun käyttäjä siirtyy kohtaan /artists/pearl-jam
tai /artists/radiohead
.
Jos polkua ei anneta, sen oletetaan olevan sama kuin reitin nimi.
Jos polku sisältää :
, sitä pidetään dynaamisena segmenttinä .
Sille annettu nimi (meidän tapauksessamme slug
) vastaa URL-osoitteen asianomaisen segmentin arvoa. slug
Yllä olevan segmentin arvo on pearl-jam
, radiohead
tai mikä tahansa muu arvo, joka on purettu URL-osoitteesta.
Ensimmäisessä vaiheessa rakennamme ruudun, joka näyttää vasemmalla olevan artistiluettelon. Tämä näyttö tulee näyttää käyttäjille, kun he siirtyvät kohtaan /artists/
Ymmärtääksesi, kuinka kyseinen näyttö on renderoitu, on aika ottaa käyttöön toinen kattava Ember-suunnitteluperiaate: kokoonpano . Yllä olevassa osassa näimme, että /artists
aktivoi artists
reitti. Sopimuksen mukaan kyseisen reitin nimi esine on ArtistsRoute
. Tämän reittiobjektin vastuulla on hakea tietoja sovelluksen hahmonnettavaksi. Näin tapahtuu reitin mallikoukussa:
App.ArtistsRoute = Ember.Route.extend({ model: function() { var artistObjects = []; Ember.$.getJSON('http://localhost:9393/artists', function(artists) { artists.forEach(function(data) { artistObjects.pushObject(App.Artist.createRecord(data)); }); }); return artistObjects; } });
Tässä katkelmassa tiedot haetaan XHR-puhelun kautta taustapäästä ja työnnetään malliobjektiksi muuntamisen jälkeen matriisiin, jonka voimme myöhemmin näyttää. Reitin vasteet eivät kuitenkaan ulotu näyttölogiikan tarjoamiseen, jota ohjain hoitaa. Katsotaanpa.
Hmmm - itse asiassa meidän ei tarvitse määritellä ohjainta tässä vaiheessa! Ember on tarpeeksi älykäs ohjaimen luomiseen tarvittaessa ja aseta ohjaimen M.odel
attribuutti itse mallikoukun palautusarvoon, nimittäin taiteilijaluetteloon. (Jälleen tämä on seurausta kokoonpanon käytäntöä koskevasta paradigmasta.) Voimme astua yhden kerroksen alaspäin ja luoda mallin luettelon näyttämiseksi:
{{#each model}} {{#link-to 'artists.songs' this class='list-group-item artist-link'}} {{name}} {{/link-to}} {{/each}} {{outlet}}
Jos tämä näyttää tutulta, se johtuu siitä, että Ember.js käyttää Ohjaustanko mallipohjat, joilla on hyvin yksinkertainen syntaksin ja avustajat, mutta jotka eivät salli ei-triviaalia logiikkaa (esim. ORing- tai ANDing-termit ehdollisessa).
Yllä olevassa mallissa iteroidaan mallin läpi (joka on asetettu aiemmin kaikkien taiteilijoiden sisältävän matriisin reitin mukaan) ja renderöimme jokaiselle sen kohteelle linkin, joka vie meidät artists.songs
taiteilijan reitti. Linkki sisältää artistin nimen. #each
ohjaustanko-ohjaaja muuttaa sen sisällä olevan ulottuvuuden nykyiseksi kohteeksi, joten {{name}}
viittaa aina toistettavan artistin nimeen.
Toinen mielenkiintoinen kohde yllä olevassa katkelmassa: {{outlet}}
, joka määrittää mallipaikat, joissa sisältö voidaan renderöidä. Pesäreittejä hahmoteltaessa ensin ulomman, resurssireitin malli, jota seuraa sisempi reitti, joka tekee mallipohjan sisällöstä {{outlet}}
määrittelee ulompi reitti. Näin tapahtuu täällä.
Sopimuksen mukaan kaikki reitit hahmottavat sisällönsä samannimiseen malliin. Yläpuolella data-template-name
yllä olevan mallin attribuutti on artists
mikä tarkoittaa, että se renderoidaan ulommalle reitille, artists
. Se määrittää oikean paneelin sisällön ulostulon, johon sisäinen reitti artists.index
tekee sisällön:
Select an artist.
Yhteenvetona voidaan todeta, että yksi reitti (artists
) renderöi sisällön vasempaan sivupalkkiin, ja sen malli on taiteilijoiden luettelo. Toinen reitti, artists.index
tekee oman sisällön artists
: n tarjoamaan paikkaan sapluuna. Se voisi hakea joitain tietoja mallina, mutta tässä tapauksessa kaikki, mitä haluamme näyttää, on staattinen teksti, joten meidän ei tarvitse.
Seuraavaksi haluamme pystyä luomaan taiteilijoita, ei vain katsomaan tylsää luetteloa.
Kun osoitin, että artists
malli, joka tekee taiteilijaluettelon, huijasin vähän. Leikasin yläosan keskittyä tärkeään. Lisään sen takaisin:
{{input type='text' class='new-artist' placeholder='New Artist' value=newName}} Add ...
Käytämme Ember-apuria, input
, tekstityypillä yksinkertaisen tekstinsyötön tekemiseksi. Siinä me sitoa | newName
: n tekstinsyötön arvo tämän mallin varmuuskopioivan ohjaimen ominaisuus ArtistsController
. Seurauksena on, että kun syötteen arvon ominaisuus muuttuu (toisin sanoen, kun käyttäjä kirjoittaa tekstin), newName
ohjaimen ominaisuus pidetään synkronoituna.
Ilmoitamme myös, että createArtist
toiminta tulisi käynnistää, kun painiketta napsautetaan. Lopuksi sidomme painikkeen käytöstä poistetun ominaisuuden disabled
-ominaisuuteen rekisterinpitäjän ominaisuus. Joten miltä ohjain näyttää?
App.ArtistsController = Ember.ArrayController.extend({ newName: '', disabled: function() { return Ember.isEmpty(this.get('newName')); }.property('newName') });
newName
on asetettu tyhjäksi alussa, mikä tarkoittaa, että tekstinsyöttö tulee olemaan tyhjä. (Muistatko, mitä kerroin siteistä? Yritä muuttaa newName
ja nähdä, että se heijastuu tekstinä syöttökentässä.)
disabled
toteutetaan siten, että kun syöttökentässä ei ole tekstiä, se palaa true
ja näin painike poistetaan käytöstä. .property
lopussa oleva kutsu tekee tästä 'lasketun ominaisuuden', toisen herkullisen siivun Ember-kakusta.
Lasketut ominaisuudet ovat ominaisuuksia, jotka riippuvat muista ominaisuuksista, jotka voivat itse olla 'normaaleja' tai laskettuja. Ember tallentaa välimuistin näiden arvoon, kunnes yksi riippuvaisista ominaisuuksista muuttuu. Sitten se laskee uudelleen lasketun ominaisuuden arvon ja tallentaa sen uudelleen välimuistiin.
Tässä on visuaalinen esitys yllä olevasta prosessista. Yhteenvetona: kun käyttäjä syöttää taiteilijan nimen, newName
ominaisuuspäivitykset, joita seuraa disabled
ja lopuksi taiteilijan nimi lisätään luetteloon.
Ajattele sitä hetkeksi. Sidosten ja laskettujen ominaisuuksien avulla voimme luoda (mallin) datan yksi totuuden lähde . Edellä mainitun uuden artistin nimen muutos laukaisee muutoksen ohjaimen ominaisuudessa, mikä puolestaan aiheuttaa muutoksen käytöstä poistetussa ominaisuudessa. Kun käyttäjä alkaa kirjoittaa uuden artistin nimeä, painike aktivoituu kuin taikalla.
Mitä suurempi järjestelmä, sitä enemmän vipua saamme 'yhden totuuden lähteen' periaatteesta. Se pitää koodimme puhtaana ja vankkana, ja omaisuusmäärittelyt ovat deklaratiivisempia.
Joissakin muissa puitteissa korostetaan myös sitä, että mallidata on ainoa totuuden lähde, mutta joko eivät mene Emberiin tai eivät tee niin perusteellista työtä. Esimerkiksi kulmalla on kaksisuuntaiset siteet - mutta sillä ei ole laskettuja ominaisuuksia. Se voi 'jäljitellä' laskettuja ominaisuuksia yksinkertaisten toimintojen avulla; Ongelmana on, että sillä ei ole mitään keinoa tietää, milloin 'laskettu ominaisuus' päivitetään, ja täten turvautuu likaisiin tarkastuksiin ja johtaa puolestaan suorituskyvyn menetykseen, varsinkin suurissa sovelluksissa.
Jos haluat oppia lisää aiheesta, suosittelen lukemaan eviltroutin blogikirjoitus lyhyemmälle versiolle tai tämä Quora-kysymys pidempään keskusteluun, jossa molempien osapuolten ydinkehittäjät punnitaan.
Palataan takaisin katsomaan, miten createArtist
toiminto luodaan laukaisun jälkeen (painikkeen painamisen jälkeen):
App.ArtistsRoute = Ember.Route.extend({ ... actions: { createArtist: function() { var name = this.get('controller').get('newName'); Ember.$.ajax('http://localhost:9393/artists', { type: 'POST', dataType: 'json', data: { name: name }, context: this, success: function(data) { var artist = App.Artist.createRecord(data); this.modelFor('artists').pushObject(artist); this.get('controller').set('newName', ''); this.transitionTo('artists.songs', artist); }, error: function() { alert('Failed to save artist'); } }); } } });
Toiminnan käsittelijät on käärittävä actions
objekti ja se voidaan määrittää reitillä, ohjaimessa tai näkymässä. Päätin määritellä sen tällä reitillä, koska toiminnan tulos ei rajoitu ohjaimeen vaan pikemminkin 'globaaliin'.
Täällä ei ole mitään hienoa. Kun taustakuva on ilmoittanut meille, että tallennustoiminto on suoritettu onnistuneesti, teemme kolme asiaa järjestyksessä:
newName
-sivulla sitominen, mikä säästää meitä joutumasta suoraan manipuloimaan DOM: ää.artists.songs
) antamalla juuri luotu taiteilija malliksi tälle reitille. transitionTo
on tapa liikkua reittien välillä sisäisesti. (Auttaja link-to
tekee sen käyttäjän toimilla.)Voimme näyttää kappaleet artistille joko napsauttamalla taiteilijan nimeä. Ohitamme myös taiteilijan, josta tulee uuden reitin malli. Jos malliobjekti välitetään näin, model
reitin koukkua ei kutsuta, koska mallia ei tarvitse ratkaista.
Aktiivinen reitti on artists.songs
ja siten ohjain ja malli ovat ArtistsSongsController
ja artists/songs
. Näimme jo, kuinka malli renderöidään artists
: n tarjoamaan ulostuloon jotta voimme keskittyä vain käsillä olevaan malliin:
(...) {{#each songs}} {{title}} {{view App.StarRating maxRating=5}} {{/each}}
Huomaa, että olen poistanut koodin uuden kappaleen luomiseksi, koska se olisi täsmälleen sama kuin uuden artistin luominen.
songs
Ominaisuus on määritetty kaikkiin taiteilijaobjekteihin palvelimen palauttamista tiedoista. Tarkka mekanismi, jolla se tehdään, ei juurikaan kiinnosta nykyistä keskustelua. Toistaiseksi riittää, että tiedämme, että jokaisella kappaleella on otsikko ja luokitus.
Otsikko näytetään suoraan mallipohjassa ja luokitus esitetään tähdillä StarRating
-sivulla näkymä. Katsotaanpa nyt.
Kappaleen luokitus on välillä 1–5 ja se näytetään käyttäjälle näkymän kautta App.StarRating
. Näkymillä on pääsy kontekstiinsa (tässä tapauksessa kappaleeseen) ja ohjaimeen. Tämä tarkoittaa, että he voivat lukea ja muokata sen ominaisuuksia. Tämä on toisin kuin toinen Ember-rakennusosa, komponentit, jotka ovat erillisiä, uudelleenkäytettäviä hallintalaitteita, joilla on pääsy vain siihen, mikä on heille siirretty. (Voimme käyttää tähtikomponenttia myös tässä esimerkissä.)
Katsotaanpa, kuinka näkymä näyttää tähtien lukumäärän ja asettaa kappaleen luokituksen, kun käyttäjä napsauttaa yhtä tähdistä:
App.StarRating = Ember.View.extend({ classNames: ['rating-panel'], templateName: 'star-rating', rating: Ember.computed.alias('context.rating'), fullStars: Ember.computed.alias('rating'), numStars: Ember.computed.alias('maxRating'), stars: function() { var ratings = []; var fullStars = this.starRange(1, this.get('fullStars'), 'full'); var emptyStars = this.starRange(this.get('fullStars') + 1, this.get('numStars'), 'empty'); Array.prototype.push.apply(ratings, fullStars); Array.prototype.push.apply(ratings, emptyStars); return ratings; }.property('fullStars', 'numStars'), starRange: function(start, end, type) { var starsData = []; for (i = start; i <= end; i++) { starsData.push({ rating: i, full: type === 'full' }); }; return starsData; }, (...) });
rating
, fullStars
ja numStars
ovat laskettuja ominaisuuksia, joista keskustelimme aiemmin disabled
: n kanssa ArtistsController
. Edellä käytin ns. Laskettua ominaisuusmakroa, josta noin tusina on määritelty Emberissä. Ne tekevät tyypillisistä lasketuista ominaisuuksista ytimekkäämpiä ja vähemmän virhealtisia (kirjoittaa). Asetin rating
olevan kontekstin (ja siten kappaleen) luokitus, kun taas määritin molemmat fullStars
ja numStars
ominaisuudet niin, että ne lukevat paremmin tähti-widgetin yhteydessä.
stars
menetelmä on tärkein vetovoima. Se palauttaa joukon tietoja tähdistä, joissa kukin kohde sisältää rating
ominaisuus (1-5) ja lippu (full
) osoittamaan, onko tähti täynnä. Tämän vuoksi niiden läpi käyminen mallissa on erittäin helppoa:
{{#each view.stars}}
{{/each}} Tämä katkelma sisältää useita huomautuksia:
each
helper osoittaa, että se käyttää näkymäominaisuutta (toisin kuin ohjaimen ominaisuus) etuliittämällä ominaisuuden nimen eteen view
.class
span-tagin attribuutille on määritetty sekoitetut dynaamiset ja staattiset luokat. Kaikki, joihin on lisätty a :
staattiseksi luokaksi, kun taas full:glyphicon-star:glyphicon-star-empty
merkintätapa on kuin JavaScriptin kolmiosainen operaattori: jos koko ominaisuus on totta, ensimmäinen luokka tulisi määrittää; jos ei, toinen.setRating
toiminta tulisi laukaista - mutta Ember etsii sitä näkymästä, ei reittiä tai ohjainta, kuten uuden artistin luomisen tapauksessa.Toiminta on siis määritelty näkymässä:
App.StarRating = Ember.View.extend({ (...) actions: { setRating: function() { var newRating = $(event.target).data('rating'); this.set('rating', newRating); } } });
Saamme luokituksen rating
data-attribuutti, jonka annoimme malliin ja asetimme sen sitten rating
laululle. Huomaa, että uutta luokitusta ei käytetä taustalla. Ei ole vaikeaa toteuttaa tätä toimintoa sen perusteella, miten taiteilija luotiin, ja se jätetään harjoitukseksi motivoituneelle lukijalle.
Olemme maistaneet useita ainesosia edellä mainitusta Ember-kakusta:
Kaunis, eikö olekin?
Emberissä on paljon enemmän kuin voisin mahtua tähän viestiin yksin. Jos haluat nähdä näyttösarjasarjan siitä, miten rakennin jonkin verran kehittyneemmän version yllä olevasta sovelluksesta ja / tai oppia lisää Emberistä, voit kirjaudu postituslistalleni saada artikkeleita tai vinkkejä viikoittain.
Toivon, että olen herättänyt ruokahalusi oppia lisää Ember.js: stä ja että ylität tässä viestissä käyttämäni esimerkkisovelluksen. Kun jatkat Ember.js: n oppimista, muista vilkaista meidän artikkeli Ember Data -operaatiosta oppiaksesi käyttämään Ember-Data-kirjastoa . Pidä hauskaa rakentaa!
Liittyvät: Ember.js ja 8 yleisintä virhettä, joita kehittäjät tekevät