Yksi vuoden suurimmista ja yleisimmistä ongelmista etupään verkkokehitys on valtion johto. Freelance-käyttöliittymäkehittäjät kuten minä, keskitymme jatkuvasti pitämään tilaobjektin synkronoituna sen näkymän ja DOM-esityksen kanssa. Käyttäjät voivat olla vuorovaikutuksessa sovelluksen kanssa monin tavoin, ja on iso tehtävä tarjota puhdas siirtyminen tilasta toiseen.
Ei niin kauan sitten verkkosovelluksilla oli paljon yksinkertaisempi tietovirta. Selain lähettää pyynnön palvelimelle, kaikki sovelluslogiikat suoritetaan palvelimella ja täydellinen HTML-näkymä lähetetään takaisin selaimeen esittelyä varten käyttäjälle. Myöhemmät käyttäjän toimet (kuten napsautukset, lomakelähetykset jne.) Laukaisevat saman virtauksen uudelleen. Sovellusten ei tarvinnut huolehtia käyttäjän tilasta, ja kukin näkymä voitiin luoda uudelleen lähettämällä uusi pyyntö palvelimelle.
Verkkosovellukset kasvoi monimutkaisuudessaan ja käyttöliittymän / käyttöliittymän käyttäjien vaatimukset etenivät myös. Koko sivun lataaminen uudelleen, kun vain yksi osa muuttui, oli tehotonta ja hidasta. Tarvitsimme nopean, rennon ja reagoivan vuorovaikutuksen, jolla oli välitön vaikutus käyttöliittymään.
JavaScript tuli apuun. Kehittäjät alkoivat kirjoittaa merkittäviä määriä koodia, joka suoritettiin selaimessa ennen pyynnön lähettämistä palvelimelle. jQuery toi myös merkittäviä etuja web-kehitykseen, koska se tarjosi yksinkertaisia ja tehokkaita valmiita ominaisuuksia, kuten asiakaspuolen vahvistus, modaaliset ikkunat, hälytysviestit, animaatiot ja jopa Ajax-pohjaiset osittaiset sivupäivitykset.
Katsotaanpa yksinkertainen esimerkki salasanan vahvuuden arvioimisesta. Jos salasana on kunnossa, syöttöruudussa tulisi olla vihreä reunus ja sen pitäisi näyttää mukava viesti. Jos salasana on heikko, syöttöruudussa tulisi olla punainen reunus ja siinä tulisi näkyä varoitusviesti. Saatamme myös näyttää hymiöt, kun salasana on riittävän vahva.
Seuraava koodi osoittaa, miten tämä voitaisiin tehdä DOM-manipulaatiolla. Täällä on paljon 'jos', eikä koodia ole kovin helppo lukea.
if (hasInputBorder()) { removeInputBorder(); } if (text.length === 0) { if (hasMessage()) { removeMessage(); } if (hasSmiley()) { removeSmiley(); } } else { var strength = getPasswordStrength(text); if (!hasInputBorder()) { addInputBorder(); } var color = (strength == 'weak' ? 'red' : 'green'); setInputBorderColor(color); var message = (strength == 'weak' ? 'Password is weak' : 'That's what I call a password!'); if (hasMessage()) { setMessageText(message); } else { addMessageWithText(message); } if (strength == 'weak') { if (hasSmiley()) { removeSmiley(); } } else { if (!hasSmiley()) { addSmiley(); } } }
Kuten yllä on esitetty, meidän on ensin tarkistettava, onko käyttäjä antanut mitään salasanaa, ja käsiteltävä tapausta, jossa salasanakenttä on tyhjä. Kaikissa tapauksissa meidän on varmistettava, että kaikki siihen liittyvät DOM-elementit päivitetään oikein. Tämä sisältää viestin, reunan ja hymiöt.
Salasanakenttämme voi olla jossakin kolmesta tilasta: tyhjä, heikko tai vahva. Ja kuten todettiin, meillä on kolme erilaista DOM-elementtiä, joihin salasanakentän tila vaikuttaa. Kaikkien yhdistelmien käsittely ja sen varmistaminen, että näkymämme näkyy oikein, lisääntyy syklomaattinen monimutkaisuus jopa yksinkertaiselle koodinpalalle, kuten tämä.
DOM toimii a säilytetty tila , mikä tarkoittaa, että se muistaa vain nykyisen tilan. Näkymämme muokkaamiseksi meidän on annettava ohjeet jokaiselle DOM-elementille ja ohjelmoitava siirtyminen.
Koodaavat siirtymät tilojen sijaan voivat olla monimutkaisia. Haarojen ja tarkastusten määrä, jotka meidän on suoritettava koodissamme, kasvaa eksponentiaalisesti hallittavien näkymien tilojen kanssa.
Esimerkissämme määriteltiin kolme näkymän tilaa, jotka antoivat meille 3 * 2 = 6
siirtymät. Yleensä, kun otetaan huomioon N tilaa, meillä on N * (N - 1) = N^2 - N
siirtymät, jotka meidän olisi mallinnettava. Ajattele vain lisääntynyttä monimutkaisuutta, jos lisäämme esimerkkiin neljännen tilan.
Ohjelmiston mallintamiseen liittyy tyypillisesti liikaa koodia siirtymät . Olisi paljon parempi, jos voimme vain määritellä näkemystilamme ja olla huolimatta kaikista yksityiskohdista siirtymisestä tilasta toiseen.
Olettaen, että voimme julistaa näkymän tila perustuu mallitilaan sen sijaan, että nimenomaisesti koodaamalla siirtyminen tilasta toiseen, meillä voi olla jotain tällaista:
var strength = getPasswordStrength(text); if (text.length == 0) { return div(input({type: 'password', value: text})); } else if (strength == 'weak') { return div( input({type: 'password', value: text, borderColor: 'red'}), span({}, 'Weak') ); } else { return div( input({type: 'password', value: text, borderColor: 'green'}), span({}, 'That's what I call a password!'), img({class: 'icon-smiley'}) ); }
Tässä meillä on kolme yksinkertaista koodihakua, jotka edustavat sovelluksemme kolmea mahdollista tilaa. Palautamme vain näkymän erittelyn jokaisessa haarassa mallin tilasta riippuen. Kaikki DOM-manipulointikoodi poistetaan; annamme vain tietoja mitä me haluamme, emmekä Miten päästä perille.
Vaikka tämä lähestymistapa vähentää merkittävästi koodin monimutkaisuutta, se olettaa myös, että joku tai joku muu huolehtii todellisesta DOM-manipuloinnista puolestamme.
Täällä Reagoi React varmistaa, että näkymän tilaa hallitaan ja päivitetään välittömästi taustalla olevan tietomallin tilan perusteella.
React on Facebookin luoma JavaScript-kirjasto. Se on suunniteltu käsittelemään verkkosovellusten käyttöliittymäosaa. Voit ajatella sitä MV-arkkitehtuurin V: nä. Se on hyvin keskittynyt. Se ei tee oletuksia muusta tekniikkapinoistasi, eikä se käsittele mitään muuta kuin komponenttien renderointia. Se ei tarjoa mitään reititysmekanismeja, malleja tai muita ominaisuuksia, jotka yleensä niputetaan suurempiin kehyksiin. Voit siis sekoittaa sen ja käyttää sitä minkä tahansa muun haluamasi kirjaston tai kehyksen kanssa.
React antaa meille mahdollisuuden määritellä käyttöliittymät komposiittikomponenttien puiksi. A Reagoi kehittäjä määrittää nämä komponentit määrittelemällä a renderöintitoiminto joka kuvaa komponenttia, kun otetaan huomioon tulotila. Tämän toiminnon pitäisi olla puhdas (ts. sillä ei saisi olla mitään sivuvaikutuksia tai riippua muusta kuin sen nimenomaisesta panoksesta).
Render-funktio palauttaa näkymän kuvauksen, jonka React kutsuu a Virtuaalinen DOM . Ajattele sitä JavaScript-objektina, joka vastaa renderoitua DOM-elementtiä.
Kun muutat komponentin tilaa, se vain renderoi itsensä ja kaikki alielementit ja palauttaa uuden Virtuaalinen DOM .
React ei myöskään tee yksinkertaista HTML-korvausta, kun se siirtyy tilasta toiseen. Se löytää erot edellisen ja uuden tilan välillä ja laskee tehokkaimman joukon DOM-operaatioita siirtymän suorittamiseksi.
Jopa ilman suorituskykyä mielessä, koodin monimutkaisuuden väheneminen on itsessään merkittävä ja antaa meille mahdollisuuden keskittää ponnistelumme sovelluksen ainutlaatuisempiin ja monimutkaisempiin osiin.
Saadaksesi hieman konkreettisemman, opetusesimerkkimme tehdään näin Reactin avulla näkymien tilojen hallintaan.
HUOMAUTUS: Seuraava koodinäyte on kirjoitettu JSX esiprosessori, joka on yleinen tapa kirjoittaa React-pohjainen käyttöliittymä.
function getPasswordStrength(text) { // Some code that calculates the strength given the password text. } var PasswordWithStrength = React.createClass({ getInitialState: function() { return {value: ''}; }, render: function() { var strength = getPasswordStrength(this.state.value); if (this.state.value.length == 0) { return ; } else if (strength == 'weak') { return Weak! ; } else { return That's what I call a password! ; } }, handleInputChange: function(ev) { this.setState({value: ev.target.value}); } }); React.render(, document.body);
Emoji
komponentti, joka renderöidään, kun salasanan vahvuus on OK, on vain yksi mukautettu komponentti (aivan kuten PasswordWithStrength
). Se määritellään seuraavasti:
var Emoji = React.createClass({ render: function() { var emojiSrc = this.props.value + '.png'; return ; } });
Oikeudenmukaisesti on kuitenkin olemassa muita asiakaspuolen JavaScript-kehyksiä (kuten Ember, Angular, Knockout ja muut), jotka ratkaisivat myös näkymän tilan hallintaongelman ja jopa lisäsivät siihen lisää ominaisuuksia. Joten, miksi haluat käyttää Reactia muiden puitteiden sijaan?
Reactilla on kaksi keskeistä etua verrattuna useimpiin muihin kirjastoihin.
Jotkut muut vaihtoehtoiset kehykset käyttävät tietojen sitomista DOM-elementtien kartoittamiseen ominaisuuksien tilaamiseen ja pitävät ne synkronoituna tarkkailemalla ominaisuusmuutoksia. Tämä lähestymistapa sallii näkymän renderoinnin kerran, ja jokainen muutos laukaisee sitten vain muutokset kyseisiin DOM-elementteihin. Muut vaihtoehdot käyttävät likainen tarkastus ; toisin sanoen, sen sijaan, että tarkkailtaisiin yksittäisiä ominaisuusmuutoksia, ne vain suorittavat eron edellisen ja uuden tilan välillä. React on enemmän samanlainen kuin jälkimmäinen lähestymistapa, mutta tilojen vertaamisen sijaan se vertaa näkymän esityksiä.
React ei sido tietoja. Kehittäjän odotetaan soittavan setState
menetelmää tai renderöi ylin komponentti uudelleen, kun tilaa muutetaan. Se kattaa yksisuuntaisen virtauksen tilasta näkymään.
Tämä käsite on helppo omaksua, koska kehittäjät eivät yleensä ajattele tietojen sitomista. Painopiste on tietojen visuaalisessa esityksessä. Siksi sinun ei tarvitse miettiä riippuvaisia ominaisuuksia, muotoilua, erityisten HTML-tunnisteiden sitomista jne. React-toiminnolla renderöit komponentin yksinkertaisesti uudelleen, kun malli muuttuu.
Ymmärtääksesi eron näkymän tilan hallinnassa tässä, verrataan Emberiä ja Reactia . Luomme objektin person
joka tuottaa koko nimen isoilla kirjaimilla. Kahden sekunnin kuluttua simuloimme muutosta ja päivitämme näkymän.
// EXAMPLE USING EMBER App = Ember.Application.create(); App.Person = Ember.Object.extend({ firstName: null, lastName: null, fullName: function() { return this.get('firstName') + ' ' + this.get('lastName'); }.property('firstName', 'lastName') }); var person = App.Person.create({ firstName: 'John', lastName: 'Doe' }); Ember.Handlebars.helper('upcase', function(value) { return value.toUpperCase(); }); App.IndexRoute = Ember.Route.extend({ model: function () { return person; } }); setTimeout(function() { person.set('firstName', 'Harry'); }, 2000); // Templates: Welcome to Ember.js
{{outlet}} The current user is: {{upcase model.fullName}}
Loimme objektin firstName
, lastName
ja fullName
ominaisuudet. Koska Ember tarkkailee ominaisuusmuutoksia, meidän oli määritettävä, että fullName
riippuu firstName
ja lastName
. Voit tehdä tämän lisäämällä .property('firstName', 'lastName')
kun määritimme fullName
.
Kahden sekunnin kuluttua person.set('firstName', 'Harry');
suoritetaan. Tämä laukaisi näkymän päivityksen ja sen sitomisen.
Tehdään nyt sama Reactissa.
// EXAMPLE USING REACT var CurrentUser = React.createClass({ render: function() { return The current user is: {this.props.user.fullName().toUpperCase()} ; } }); var person = { firstName: 'John', lastName: 'Doe', fullName: function() { return this.firstName + ' ' + this.lastName; } }; var currentUser = React.render(, document.body); setTimeout(function() { person.firstName = 'Harry'; currentUser.setProps({user: person}); }, 2000);
Vaikka Ember-koodi on yksinkertainen ja helppo lukea, on selvää, että React voittaa yksinkertaisuudessa. person
on tavallinen JavaScript-objekti, jossa fullName
yksinkertaisesti olla funktio.
Jokaisella vaihtoehtoisella kehyksellä on erilainen tapa käsitellä malleja. Jotkut heistä käyttävät merkkijonoja, jotka on käännetty JavaScriptiksi, kun taas toiset käyttävät suoraan DOM-elementtejä. Suurin osa niistä käyttää mukautettuja HTML-määritteitä ja tunnisteita, jotka sitten 'käännetään' HTML-muotoon.
Mallit eivät ole osa JavaScript-koodia. Tämän vuoksi kukin vaihtoehto tarpeisiin mukautettu tapa edustaa yleisiä operaatioita, ehdollisia, iteraatioita, kutsutoimintoja jne. Ne kaikki lopulta luovat uuden pseudokielen, jonka kehittäjien on opittava.
Reactissa ei ole mallia, kaikki on vain vanha JavaScript.
React käyttää JavaScriptin täyttä tehoa luodakseen näkymän. Komponentin renderöintimenetelmä on JavaScript-funktio.
JSX on saatavana esiprosessorina, joka muuttaa 'HTML-tyyppisen syntaksin' normaaliksi JavaScriptiksi, mutta JSX on valinnainen ja voit vapaasti käyttää tavallista JavaScriptiä ilman esiprosessoreita. Voit myös hyödyntää olemassa olevia JavaScript-työkaluja. Linssit, esiprosessorit, tyyppihuomautukset, pienentäminen, koodin poistaminen jne.
Käytetään jälleen konkreettista esimerkkiä verrattaessa React-vaihtoehtoa näkemystilan hallinnan vaihtoehtoisiin puitteisiin.
Seuraava opetusohjelma on esimerkki käytöstä KulmaJS listata hashtagit ja twiittien määrä kullekin niistä. Luettelo on lajiteltu lukumäärän mukaan, ja viesti näkyy, jos hashtageja ei ole.
- {{hashTag.name}} - {{hashTag.tweetCount}} tweets
No hashtags found!
Voidakseen tehdä tämän luettelon, kehittäjän on opittava AngularJS directives
, ng-show
ja ng-repeat
. Sitten hänen on opittava AngularJS filters
ymmärtää orderBy
. Paljon työtä yksinkertaisesta asiasta, kuten luettelon tuottamisesta!
Tarkastellaan nyt React-esimerkkiä, joka tekee saman:
// EXAMPLE USING REACT function byTweetCountDesc(h1, h2) { return h2.tweetCount - h1.tweetCount; } //... render: function() { if (this.state.hashTags.length > 0) { var comps = this.state.hashTags.sort(byTweetCountDesc).map(function(hashTag, index) { return {hashTag.name} - {hashTag.tweetCount} tweets ; }); return {comps}
; } else { return No hashtags found! } }
Vaikka käytämme 'edistyneempää' lähestymistapaa ja JSX: ää, jokainen web-kehittäjä, jolla on perustiedot JavaScriptistä, voi helposti lukea yllä olevan koodin ja ymmärtää, mitä se tekee. Tavallinen ehdollinen tarkistus käyttäen if
, iterointi käyttäen map()
ja tavallinen 'lajittelu ()' tulee luonnollisesti kenellekään kehittäjälle, joten ei ole mitään ylimääräistä syntaksia tai muita opittavia käsitteitä.
Tämän React.js-opetusohjelman tärkein takeaway on se, että Reactin avulla voit keskittyä todelliseen näkymän tilan hallintaan siirtymien sijaan, mikä yksinkertaistaa työtäsi ja sovellustasi.
React-oppimiskäyrä on melko triviaali. Ei mukautettua mallikieliä hallittavaksi, ei tietojen sitomista, josta huolehtia, ja kaikki tulee JavaScript-toiminnoista, jotka kuvaavat käyttöliittymän elementtejä.
Jos haluat lisätietoja sovelluskoodin yksinkertaistamisesta Reactin avulla, katso tämä Steven Luscherin puhe, Hajotuskoodi React .
Tässä on joitain lisälukemia kaikille, jotka haluavat ottaa seuraavan vaiheen ja aloittaa Reactin käytön: