Innovatsiooni kiirus JavaScripti Landis on nii suur, et mõned inimesed isegi arvavad seda kontraproduktiivne . Raamatukogu võib mõne kuu jooksul minna varakult kasutusele võetavatest mänguasjadest tipptasemel vananemisele. Võimalus tuvastada tööriist, mis jääb asjakohaseks veel vähemalt aastaks, on muutumas kunstiks.
Kui React.js oli vabastati kaks aastat tagasi õppisin just nurka ja lasin Reacti kiiresti hämaraks, veel üheks, mallide teegiks. Nende kahe aasta jooksul saavutas Angular tõepoolest tugeva koha JavaScripti arendajad ja sai peaaegu kaasaegse JS-i arenduse sünonüümiks. Hakkasin Angulari nägema isegi väga konservatiivsetes ettevõtluskeskkondades ja pidasin selle helget tulevikku iseenesestmõistetavaks.
Kuid äkki juhtus kummaline asi. Tundub nurgeline sai Osborne'i efekti ohver või “surm etteteatamise teel”. Meeskond teatas, et esiteks on Angular 2 täiesti erinev, ilma nurga 1-st selge rändeteeta, ja teiseks, et Angular 2 pole saadaval veel umbes aasta. Mida ütleb see kellelegi, kes soovib uut veebiprojekti alustada? Kas soovite kirjutada oma uue projekti raamistikku, mis uue versiooni väljalaskega vananeb?
See arendajate ärevus mängis Reacti kätte, kes püüdis end kogukonnas sisse seada. Kuid React turustas ennast alati MV-s V-na. See tekitas veebiarendajates teatavat pettumust, kes on harjunud töötama täielike raamistikega. Kuidas puuduolevad tükid täita? Kas peaksin ise kirjutama? Kas peaksin kasutama lihtsalt olemasolevat raamatukogu? Kui jah, siis milline?
Kindlasti oli Facebookil (React.js loojatel) veel üks äss augus: The Flux töövoog, mis lubas täita puuduvad funktsioonid „M” ja „C”. Asjade veelgi huvitavamaks muutmiseks teatas Facebook, et Flux on 'muster', mitte raamistik ja nende Fluxi rakendamine on vaid üks mustri näide. Nende sõnade kohaselt oli nende rakendamine tõesti lihtsustatud ja hõlmas palju nende kirjutamist paljusõnaline , korduv boilerplat asjade käima saamiseks.
Avatud lähtekoodiga kogukond tuli appi ja aasta hiljem on meil kümneid Fluxi teeke ja isegi mõned metaprojektid, mille eesmärk on neid võrreldes . See on hea asi; Mingi valmis ettevõtte raamistiku väljaandmise asemel on Facebook suutnud huvi kogukonna vastu äratada ja julgustas inimesi oma lahendusi välja pakkuma.
Sellel lähenemisel on üks huvitav kõrvalmõju: kui peate oma täieliku raamistiku saamiseks ühendama palju erinevaid teeke, pääsete tõhusalt hankija lukustamisest ja teie enda raamistiku ehitamisel ilmnenud uuendusi saab hõlpsasti taaskasutada mujal.
Sellepärast on uus kraam ümber Reageeri on nii huvitav; suurema osa sellest saab teistes JavaScripti keskkondades hõlpsasti taaskasutada. Isegi kui te ei kavatse Reactit kasutada, on selle ökosüsteemi vaatamine inspireeriv. Võite oma ehitussüsteemi lihtsustada, kasutades võimsat, kuid suhteliselt hõlpsasti konfigureeritavat moodulipaketti Veebipakk või alustage ECMAScript 6 ja isegi ECMAScript 7 kirjutamist täna Paabel koostaja.
Selles artiklis tutvun huvitavate funktsioonide ja teekidega, mis on saadaval. Niisiis, uurime Reacti ökosüsteemi!
Ehitamissüsteem on vaieldamatult esimene asi, millest uue veebirakenduse loomisel peaksite hoolima. Ehitussüsteem pole mitte ainult skriptide käitamise tööriist, vaid JavaScripti maailmas kujundab see tavaliselt teie rakenduse üldist struktuuri. Ehitussüsteemi peamised ülesanded on järgmised:
Viimastel aastatel on Yeoman töövoog koos Bower ja Maa esitati kui Püha kolmainsus moodsa arenduse arendamine, vastavalt katelde genereerimise, pakettide haldamise ja ühiste ülesannete käitamise probleemide järkjärguline muutmine Gruntilt Gulp hiljuti.
React keskkonnas saate need julgelt unustada. Mitte et te neid ei saaks kasutada, kuid on tõenäoline, et saate lihtsalt kasutamisest vabaneda Veebipakk ja vana hea NPM . Kuidas on see võimalik? Webpack on moodulite komplekt, mis rakendab ÜhineJS moodul süntaks, mis on levinud Node.js maailmas, ka brauseris. See muudab asjad tegelikult lihtsamaks, kuna kasutajaliidese jaoks pole vaja veel üht paketihaldurit õppida; kasutate lihtsalt NPM-i ja jagate sõltuvusi serveri ja kasutajaliidese vahel. Samuti ei pea te tegelema JS-failide õiges järjekorras laadimise probleemiga, kuna see järeldatakse igas failis määratud sõltuvuse impordist ja kogu sülem on õigesti ühendatud ühe laaditava skriptiga.
Veebipakk
Et asi veelgi atraktiivsem oleks, on Webpack erinevalt vanemast nõbust Sirvige , saab hakkama ka teiste varaliikidega. Näiteks koos laadurid , saate muuta mis tahes varafaili JavaScripti funktsiooniks, mis kas viitab või laadib viidatud faili. Niisiis, unustage HTML-i varade käsitsi eeltöötlus ja viitamine. Lihtsalt require
teie CSS / SASS / LESS failid JavaScripti kaudu ja Webpack hoolitseb ülejäänu lihtsa abil konfigureerimisfail . Webpack sisaldab ka arenduse veebiserverit ja failide jälgijat. Lisaks saate kasutada nuppu 'scripts'
sisestage package.json
määratleda kestvooderdised:
{ 'name': 'react-example-filmdb', 'version': '0.0.1', 'description': 'Isomorphic React + Flux film database example', 'main': 'server/index.js', 'scripts': { 'build': './node_modules/.bin/webpack --progress --stats --config ./webpack/prod.config.js', 'dev': 'node --harmony ./webpack/dev-server.js', 'prod': 'NODE_ENV=production node server/index.js', 'test': './node_modules/.bin/karma start --single-run', 'postinstall': 'npm run build' } ... }
Ja see on peaaegu kõik, mida vajate Gulpi ja Boweri asendamiseks. Muidugi saate Yeomanit kasutada ka rakenduse katlakivi genereerimiseks. Ärge laske end heidutada, kui vajaliku kraami jaoks pole Yeomani generaatorit (kõige tipptasemel raamatukogudel pole seda sageli). Ikka saate GitHubist lihtsalt katelde kloonida ja häkkida.
Seotud: Kuidas reageerivad komponendid muudavad kasutajaliidese testimise lihtsaksJavaScripti keele arendamise tempo on viimastel aastatel oluliselt suurenenud ning pärast veidruste kõrvaldamise ja keele stabiliseerimise perioodi näeme nüüd uusi võimsaid funktsioone. ECMAScript 6 (ES6) spetsifikatsiooni mustand on viimistletud ja kuigi seda pole veel ametlikuks muudetud, on see juba laialdaselt kasutusele võetud. ECMAScript 7 (ES7) väljatöötamine on pooleli, kuid tipptasemel raamatukogud on juba kasutusele võtnud paljud selle funktsioonid.
ECMAScript 7
Kuidas on see võimalik? Võib-olla arvate, et te ei saa kasutada neid uusi läikivaid JavaScripti funktsioone enne, kui neid Internet Explorer toetab, kuid mõelge uuesti. ES-transpilaatorid on juba nii üldlevinud, et saame hakkama ka ilma korraliku brauseritoeta. Parim praegu kättesaadav ES-transpiler on Paabel : see võtab teie uusima ES6 + koodi ja teisendab selle vanilje ES5-ks, nii et võite kasutada kõiki uusi ES-i funktsioone kohe, kui see on leiutatud (ja Babelis rakendatud, mis juhtub tavaliselt üsna kiiresti).
Paabel
Uusimad JavaScripti funktsioonid on kasulikud kõigis esiotsa raamistikes ning Reactit on hiljuti värskendatud, et see sobiks kenasti ES6 ja ES7 spetsifikatsioonidega. Need uued funktsioonid peaksid Reactiga arendades kõrvaldama palju peavalusid. Vaatame mõningaid kõige kasulikumaid lisandeid ja kuidas need saavad Reacti projektist kasu olla. Hiljem näeme, kuidas kasutada mõningaid kasulikke tööriistu ja teeke rakendusega React, kasutades seda täiustatud süntaksit.
Objektorienteeritud programmeerimine on võimas ja laialt omaksvõetud paradigma, kuid JavaScripti omaksvõtt on veidi eksootiline. Enamik esiotsa raamistikke, olgu see siis selgroog, Ember, Angular või React, on seega kasutanud oma varjatud viise klasside määratlemiseks ja objektide loomiseks. Kuid ES6-ga on meil nüüd JavaScripti traditsioonilised klassid ja nende enda rakendamise kirjutamise asemel on lihtsalt mõttekas neid kasutada. Niisiis, selle asemel, et:
React.createClass({ displayName: 'HelloMessage', render() { return Hello {this.props.name} ; } })
saame kirjutada:
class HelloMessage extends React.Component { render() { return Hello {this.props.name} ; } }
Täpsema näite saamiseks kaaluge seda koodi vana süntaksit kasutades:
React.createClass({ displayName: 'Counter', getDefaultProps: function(){ return {initialCount: 0}; }, getInitialState: function() { return {count: this.props.initialCount} }, propTypes: {initialCount: React.PropTypes.number}, tick() { this.setState({count: this.state.count + 1}); }, render() { return ( Clicks: {this.state.count} ); } });
Ja võrrelge ES6 versiooniga:
class Counter extends React.Component { static propTypes = {initialCount: React.PropTypes.number}; static defaultProps = {initialCount: 0}; constructor(props) { super(props); this.state = {count: props.initialCount}; } state = {count: this.props.initialCount}; tick() { this.setState({count: this.state.count + 1}); } render() { return ( Clicks: {this.state.count} ); } }
Siin on Reacti elutsükli meetodid getDefaultProps
ja getInitialState
pole enam vajalikud. getDefaultProps
saab staatilise klassi muutujaks defaultProps
ja algseis on konstruktoris just määratletud. Ainus puudus on see, et meetodid ei ole enam automaatsed, seega peate kasutama bind
- st JSX .
Kaunistajad on ES7 kasulik funktsioon. Need võimaldavad teil suurendada funktsiooni või klassi käitumist, pakkides selle teise funktsiooni sisse. Oletame näiteks, et soovite, et mõnes oma komponendis oleks sama muudatuste käitleja, kuid te ei soovi pühenduda pärandi antipattern . Selle asemel võite kasutada klassi dekoraatorit. Määratleme dekoraatori järgmiselt:
addChangeHandler: function(target) { target.prototype.changeHandler = function(key, attr, event) { var state = {}; state[key] = this.state[key] || {}; state[key][attr] = event.currentTarget.value; this.setState(state); }; return target; }
Siinkohal on oluline, et funktsioon addChangeHandler
lisab changeHandler
funktsiooni sihtklassi prototüübile.
Kaunistaja pealekandmiseks võiksime kirjutada:
MyClass = changeHandler(MyClass)
või elegantsemalt, ES7 süntaksiga:
@addChangeHandler class MyClass { ... }
Mis puutub changeHandler
sisu funktsioon ise, kuna Reactil puudub andmete kahepoolne sidumine, võib Reactis töötamine sisenditega olla tüütu. changeHandler
funktsioon püüab seda hõlbustada. Esimene parameeter määrab key
olekuobjektil, mis toimib sisendi andmeobjektina. Teine parameeter on atribuut, millele sisendvälja väärtus salvestatakse. Need kaks parameetrit määratakse JSX-i abil, kasutades bind
märksõna.
@addChangeHandler class LoginInput extends React.Component { constructor(props) { super(props); this.state = { login: {} }; } render() { return ( ) } }
Kui kasutaja muudab kasutajanime välja, salvestatakse selle väärtus kausta this.state.login.username
ilma, et oleks vaja määratleda rohkem kohandatud käitlejaid.
JavaScripti dünaamiline this
kontekst on olnud arendajatele pidev piin, sest mõnevõrra tahtmatult on this
sisestatud funktsiooni kontekst lähtestatakse globaalseks, isegi klassi sees. Selle parandamiseks on tavaliselt vaja salvestada this
mõnele välise ulatuse muutujale (tavaliselt _this
) ja kasutage seda sisemistes funktsioonides:
class DirectorsStore { onFetch(directors) { var _this = this; this.directorsHash = {}; directors.forEach(function(x){ _this.directorsHash[x._id] = x; }) } }
Uue ES6 süntaksiga function(x){
saab ümber kirjutada (x) => {
. See noolemeetodi määratlus ei seo ainult õigesti this
välise ulatuseni, kuid on ka tunduvalt lühem, mis kindlasti loeb palju asünkroonse koodi kirjutamisel.
onFetch(directors) { this.directorsHash = {}; directors.forEach((x) => { this.directorsHash[x._id] = x; }) }
ES6-s sisse viidud ülesannete ümberkorraldamine võimaldab teil liiteobjekti ülesande vasakul küljel:
var o = {p: 42, q: true}; var {p, q} = o; console.log(p); // 42 console.log(q); // true
See on tore, kuid kuidas see meid Reactis tegelikult aitab? Vaatleme järgmist näidet:
function makeRequest(url, method, params) { var config = { url: url, method: method, params: params }; ... }
Destruktureerimise abil saate salvestada paar klahvivajutust. Võtmed sõna otseses mõttes {url, method, params}
määratakse automaatselt võtmetega samade nimedega väärtused ulatusest. Seda kõnepruuki kasutatakse üsna sageli ja korduse välistamine muudab koodi vähem veaohtlikuks.
function makeRequest(url, method, params) { var config = {url, method, params}; ... }
Ümberkorraldamine võib aidata teil laadida ainult mooduli alamhulka:
const {clone, assign} = require('lodash'); function output(data, optional) { var payload = clone(data); assign(payload, optional); }
Funktsiooni argumendid on ES6-s võimsamad. Lõpuks saate määrata vaikimisi argument:
function http(endpoint, method='GET') { console.log(method) ... } http('/api') // GET
Väsinud rammestumisega kohmetutega arguments
objekt? Uue spetsifikatsiooniga saate puhata argumentidest massiivina:
function networkAction(context, method, ...rest) { // rest is an array return method.apply(context, rest); }
Ja kui teile ei meeldi helistada apply()
, saate lihtsalt levik massiiv funktsiooni argumentideks:
myArguments = ['foo', 'bar', 123]; myFunction(...myArguments);
ES6 tutvustas JavaScripti generaatoreid. Generaator on põhimõtteliselt JavaScripti funktsioon, mille käivitamise saab peatada ja seejärel hiljem oma olekut meenutades jätkata. Iga kord yield
märksõna, täitmine on peatatud ja yield
argument edastatakse tagasi kutsuvale objektile:
function* sequence(from, to) { console.log('Ready!'); while(from <= to) { yield from++; } }
Siin on näide selle generaatori toimimisest:
> var cursor = sequence(1,3) Ready! > cursor.next() { value: 1, done: false } > cursor.next() { value: 2, done: false } > cursor.next() { value: 3, done: false } > cursor.next() { value: undefined, done: true }
Kui kutsume generaatorfunktsiooni, käivitub see kuni esimese yield
ja lõpeb. Pärast helistamist next()
tagastab see esimese väärtuse ja jätkab käivitamist. Iga yield
tagastab teise väärtuse, kuid pärast kolmandat kõnet lõpetatakse generaatori funktsioon ja iga järgmine kõne next()
naaseb { value: undefined, done: true }
.
Muidugi pole generaatorite mõte luua keerukaid numbrilisi järjestusi. Põnev osa on nende võime peatada ja jätkata funktsioonide käivitamist, mida saab kasutada asünkroonse programmivoo juhtimiseks ja lõpuks neist ärritavatest tagasihelistamisfunktsioonidest vabanemiseks.
Selle idee demonstreerimiseks vajame kõigepealt asünkroonset funktsiooni. Tavaliselt on meil mõni sisend- / väljundoperatsioon, kuid lihtsuse huvides kasutagem lihtsalt setTimeout
ja tagastage a lubadus . (Pange tähele, et ka ES6 tutvustas põlised lubadused JavaScripti.)
function asyncDouble(x) { var deferred = Promise.defer(); setTimeout(function(){ deferred.resolve(x*2); }, 1000); return deferred.promise; }
Järgmiseks vajame tarbijafunktsiooni:
function consumer(generator){ var cursor = generator(); var value; function loop() { var data = cursor.next(value); if (data.done) { return; } else { data.value.then(x => { value = x; loop(); }) } } loop(); }
See funktsioon võtab argumendiks mis tahes generaatori ja kutsub edasi next()
sellel seni, kuni on väärtusi yield
Sel juhul on antud väärtused lubadused ja seetõttu on vaja oodata lubaduste lahendamist ja kasutada rekursiooni loop()
pesitsevate funktsioonide vahel silmuse saamiseks.
Tagastusväärtus lahendatakse then()
-s käitleja ja edastatud value
-le, mis on määratletud välimises ulatuses ja mis edastatakse next(value)
helistama. See kõne muudab väärtuse vastava saagise avaldise tulemuseks. See tähendab, et nüüd saame kirjutada asünkroonselt ilma tagasihelistamiseta:
function* myGenerator(){ const data1 = yield asyncDouble(1); console.log(`Double 1 = ${data1}`); const data2 = yield asyncDouble(2); console.log(`Double 2 = ${data2}`); const data3 = yield asyncDouble(3); console.log(`Double 3 = ${data3}`); } consumer(myGenerator);
Generaator myGenerator
peatatakse iga yield
korral, oodates, kuni tarbija täidab antud lubaduse. Ja tõepoolest näeme arvutatud numbreid konsoolis ühe sekundi intervallidega.
Double 1 = 2 Double 2 = 4 Double 3 = 6
See näitab põhimõistet, kuid ma ei soovita seda koodi tootmisel kasutada. Selle asemel valige hästi testitud raamatukogu, näiteks Mida . See võimaldab teil async-koodi hõlpsasti kirjutada koos saagisega, sealhulgas tõrketeadetega:
co(function *(){ var a = yield Promise.resolve(1); console.log(a); var b = yield Promise.resolve(2); console.log(b); var c = yield Promise.resolve(3); console.log(c); }).catch(function(err){ console.error(err.stack); });
Niisiis, see näide näitab, kuidas asünkroonset koodi kirjutada ilma tagasihelistamiseta, kasutades ES6 generaatoreid. ES7 kasutab seda lähenemist veel ühe sammu edasi, tuues sisse async
ja await
märksõnad ja eemaldatakse vajadus generaatoriteegi järele. Selle võimaluse korral näeks eelmine näide välja selline:
async function (){ try { var a = await Promise.resolve(1); console.log(a); var b = await Promise.resolve(2); console.log(b); var c = await Promise.resolve(3); console.log(c); } catch (err) { console.error(err.stack); } };
Minu arvates võtab see JavaScripti asünkroonse koodiga töötamise valu ära. Mitte ainult Reactis, vaid ka igal pool mujal.
Generaatorid pole mitte ainult ülevaatlikumad ja otsekohesemad, vaid võimaldavad meil kasutada ka tehnikaid, mida tagasihelistamise korral oleks väga raske rakendada. Silmapaistev näide generaatori headusest on ka vahevara kogu Node.js. Selle eesmärk on asendada Express ja selle eesmärgi saavutamiseks on sellel üks tapjafunktsioon: vahevara kett ei voola mitte ainult allavoolu (koos kliendi sooviga), aga ka ülesvoolu , mis võimaldab serveri vastust veelgi muuta. Vaatleme järgmist koa serveri näidet:
// Response time logger middleware app.use(function *(next){ // Downstream var start = new Date; yield next; // Upstream this.body += ' World'; var ms = new Date - start; console.log('%s %s - %s', this.method, this.url, ms); }); // Response handler app.use(function *(){ this.body = 'Hello'; }); app.listen(3000);
Palun
Vastuse vahevara yield
s allavoolu vastuse käitlejaks, mis määrab vastuse keha, ja ülesvoolu voos (pärast avaldist yield
), this.body
on lubatud, samuti muud funktsioonid, näiteks aja logimine, mis on võimalik, kuna eel- ja allavoolu jagavad sama funktsiooni konteksti. See on palju võimsam kui Ekspress , kus sama asja saavutamise katse lõppeks nii:
var start; // Downstream middleware app.use(function(req, res, next) { start = new Date; next(); // Already returned, cannot continue here }); // Response app.use(function (req, res, next){ res.send('Hello World') next(); }); // Upstream middleware app.use(function(req, res, next) { // res already sent, cannot modify var ms = new Date - start; console.log('%s %s - %s', this.method, this.url, ms); next(); }); app.listen(3000);
Tõenäoliselt saate siin juba märgata, mis viga on; kasutades globaalset start
muutuja tulemuseks on võistlustingimus, tagastades samaaegsete taotlustega jama. Lahendus on mõni ilmselge lahendus ja võite unustada reaktsiooni muutmise ülesvoolu voos.
Samuti saate koa kasutamisel generaatori asünkroonse töövoo tasuta:
app.use(function *(){ try { const part1 = yield fs.readFile(this.request.query.file1, 'utf8'); const part2 = yield fs.readFile(this.request.query.file2, 'utf8'); this.body = part1 + part2; } catch (err) { this.status = 404 this.body = err; } }); app.listen(3000);
Võite ette kujutada lubadusi ja tagasihelistamisi, mis on seotud selle väikese näite uuesti loomisega Expressis.
Kuidas on kogu see Node.js jutt seotud Reactiga? Node on Reactile sobiva tagumise otsa kaalumisel esimene valik. Kuna sõlm on kirjutatud ka JavaScripti, toetab see koodi jagamist taguotsa ja esiotsa vahel, võimaldades meil ehitada isomorfne Veebirakendustele reageerimine. Aga sellest hiljem lähemalt.
React on suurepärane komponeeritavate kuvakomponentide loomisel, kuid vajame kogu rakenduse andmete ja oleku haldamiseks mingit viisi. Peaaegu üldiselt on kokku lepitud, et Reacti täiendab kõige paremini rakenduse Flux arhitektuur. Kui olete Fluxis täiesti uus, soovitan kiiret värskenda .
Flux
Mis pole nii universaalselt kokku lepitud, on see, milline paljudest Fluxi rakendustest valida. Facebook Flux oleks ilmne valik, kuid enamiku inimeste jaoks on see liiga paljuütlev. Alternatiivsed rakendused keskenduvad enamasti vajaliku katlaplaadi hulga vähendamisele tavapärase konfiguratsiooni lähenemisviisiga ning ka mõnede mugavamate funktsioonidega kõrgemat järku komponentide jaoks, serveripoolsel renderdamisel jne. Näha on mõnda populaarseimat võistlejat, kellel on erinevad populaarsusmõõdikud siin . Olen uurinud Alt, Reflux, Flummox, Fluxxor ja Marty.js.
Minu viis valida õige raamatukogu pole kuidagi objektiivne, kuid see võib siiski aidata. Fluxxor oli üks neist esimestest raamatukogudest, mille ma välja vaatasin, kuid nüüd tundub see veidi aegunud. Marty.js on huvitav ja sellel on palju funktsioone, kuid see hõlmab siiski palju katla plaate ja mõned funktsioonid tunduvad üleliigsed. Refluks näeb hea välja ja on mõnevõrra veojõuga, kuid tunneb algajatele natuke raskusi ning puudub ka korralik dokumentatsioon. Flummox ja Kõik on väga sarnased, kuid Altil näib olevat veelgi vähem katelde, väga aktiivse arendusega, ajakohane dokumentatsioon ja abivalmis Lõtv kogukonna. Seetõttu valisin Alt.
Alt Flux
Altiga muutub Fluxi töövoog palju lihtsamaks, kaotamata selle võimsust. Facebooki voog dokumentatsioon ütleb dispetšeri kohta palju, kuid võime seda vabalt ignoreerida, sest aastal Kõik , on dispetšer vaikimisi juhtmega ühendatud toimingutega ja tavaliselt ei vaja see kohandatud koodi. See jätab meile õiguse kauplustes , tegevused ja komponendid . Neid kolme kihti võib kasutada nii, et need kaardistuvad kenasti MVC mõttemudel: Kauplused on Mudelid , toimingud on Kontrollerid ja komponendid on Vaated . Peamine erinevus seisneb Flux-mustri keskses ühesuunalises andmevoogus, mis tähendab, et kontrollerid (toimingud) ei saa vaateid (komponente) otseselt modifitseerida, vaid võivad selle asemel käivitada ainult mudeli (poe) muudatused, millega vaated on passiivselt seotud. See oli juba mõne jaoks parim tava valgustatud Nurgaarendajad.
Töövoo on järgmine:
Alt Fluxi teegi kasutamisel on toimingud tavaliselt kahe maitsega: automaatsed ja käsitsi. Automaatsed toimingud luuakse generateActions
abil funktsioon ja nad lähevad otse dispetšerile. Manuaalsed meetodid on määratletud teie tegevusklasside meetoditena ja need võivad dispetšeri juurde minna täiendava kasuliku koormusega. Automaatsete toimingute kõige levinum kasutusviis on kaupluste teavitamine mõnest rakenduse sündmusest. Käsitsi toimimine on muu hulgas eelistatud serverite interaktsioonide käsitlemise viis.
Nii et REST API kõned kuuluvad toimingutesse. Kogu töövoog on järgmine:
AJAX-i päringute jaoks saame kasutada aksiosid raamatukogu, mis muu hulgas tegeleb JSON-i andmete ja päistega sujuvalt. Lubaduste või tagasihelistamiste asemel võime kasutada ES7 async
/ await
muster. Kui POST
vastuse olek pole 2XX, visatakse viga ja me saadame kas tagastatud andmed või vastuvõetud vea.
Alt-töövoo lihtsa näite vaatame sisselogimislehelt. Väljalogimise toiming ei pea midagi erilist tegema, teavitage ainult poodi, et saaksime selle automaatselt genereerida. Sisselogimistoiming on käsitsi ja eeldab toimingu loojale parameetrina sisselogimisandmeid. Pärast serverilt vastuse saamist edastame kas edukuse andmed või kui tõrge ilmneb, saadame saadud vea.
class LoginActions { constructor() { // Automatic action this.generateActions('logout'); } // Manual action async login(data) { try { const response = await axios.post('/auth/login', data); this.dispatch({ok: true, user: response.data}); } catch (err) { console.error(err); this.dispatch({ok: false, error: err.data}); } } } module.exports = (alt.createActions(LoginActions));
Kauplusel Flux on kaks eesmärki: sellel on tegevuskäsitlejad ja see kannab olekut. Jätkame oma sisselogimislehe näidet, et näha, kuidas see töötab.
Loome praeguse sisselogitud kasutaja jaoks LoginStore
kahe oleku atribuudiga: user
ja praeguse sisselogimisega seotud tõrke korral error
Katla vähendamise vaimus võimaldab Alt meil seonduda kõigi ühe klassi toimingutega ühe funktsiooniga bindActions
class LoginStore { constructor() { this.bindActions(LoginActions); this.user = null; this.error = null; } ...
Töötleja nimed on määratletud kokkuleppeliselt, ette on
vastava toimingu nimele. Nii et login
tegevusega tegeleb onLogin
ja nii edasi. Pange tähele, et toimingu nime algustäht kirjutatakse suurtähega camelCase stiilis. Meie LoginStore
-s on järgmised käitlejad, keda kutsutakse vastavate toimingutega:
... onLogin(data) { if (data.ok) { this.user = data.user; this.error = null; router.transitionTo('home'); } else { this.user = null; this.error = data.error } } onLogout() { this.user = null; this.error = null; } }
Tavaline viis kaupluste sidumiseks komponentidega on kasutada mingisugust React mixini. Aga kuna miksid lähevad moest väljas , peab olema mõni muu viis. Üks uutest lähenemistest on kasutada kõrgemat järku komponente. Võtame oma komponendi ja asetame selle ümbrise komponendi sisse, mis hoolitseb kaupluste kuulamise ja uuesti renderdamise eest. Meie komponent saab poe oleku props
See lähenemine on kasulik ka meie koodi korrastamiseks tark ja loll viimasel ajal trendikaks muutunud komponendid. Alt puhul rakendab komponendi ümbrise AltContainer
:
export default class Login extends React.Component { render() { return ( )} }
Meie LoginPage
komponent kasutab ka changeHandler
varem tutvustatud dekoraator. Andmed pärineb LoginStore
kasutatakse ebaõnnestunud sisselogimise korral vigade kuvamiseks ja uuesti renderdamise eest hoolitseb AltContainer
Sisselogimisnupul klõpsamine käivitab login
toiming, lõpetades Alt fluxi töövoo:
@changeHandler export default class LoginPage extends React.Component { constructor(props) { super(props); this.state = { loginForm: {} }; } login() { LoginActions.login(this.state.loginForm) } render() { return ( {{this.props.LoginStore.error}} Login )} }
Isomorfsed veebirakendused on tänapäeval kuum teema, kuna need lahendavad traditsiooniliste ühe lehe rakenduste suurimaid ülesandeid. Nendes rakendustes loob märgistuse brauseris Java dünaamiliselt. Tulemuseks on see, et sisu pole saadaval klientidele, kelle JavaScript on välja lülitatud, eriti otsingumootorite veebirobotid. See tähendab, et teie veebileht ei ole indekseeritud ja seda ei kuvata otsingutulemites. On võimalusi selle ümber töötama , kuid need pole kaugeltki optimaalsed. Isomorfne lähenemine üritab seda probleemi lahendada, renderdades serveris ühe lehe rakenduse taotletud URL-i. Node.js-ga on teil serveris JavaScripti, mis tähendab, et React saab käivitada ka serveripoolse. See ei tohiks olla liiga raske, eks?
Üheks takistuseks on see, et mõnel Fluxi teegil, eriti neil, kus kasutatakse üksikuid, on raskusi serveripoolse renderdamisega. Kui teil on üksikud Fluxi poed ja mitu samaaegset päringut oma serverisse, lähevad andmed segi. Mõni teek lahendab selle Flux-eksemplaride abil, kuid sellega kaasnevad muud puudused, eriti vajadus need eksemplarid oma koodis ringi viia. Alt pakub ka Fluxi eksemplare, kuid on lahendanud ka serveripoolse renderdamise probleemi singlettidega; see loputab kauplusi pärast iga päringut, nii et iga samaaegne taotlus algab puhta lehega.
Serveripoolse renderdamise funktsionaalsuse tuuma pakub React.renderToString
Serveris käitatakse ka kogu Reacti esiotsa rakendus. Nii ei pea me ootama kliendipoolset JavaScripti märgistuse loomiseks; see on eelnevalt ehitatud serverisse juurdepääsetava URL-i jaoks ja saadetud brauserisse HTML-iga. Kui klient JavaScripti töötab, jätkub see sealt, kus server on pooleli jäänud. Selle toetamiseks saame kasutada Major raamatukogu, mis on mõeldud kasutamiseks Alt-ga.
Esiteks lähtestame Fluxi serveris, kasutades alt.bootstrap
Fluxi kauplused on võimalik renderdamiseks eelnevalt täita. Samuti on vaja otsustada, millist komponenti millise URL-i jaoks renderdada, mis on kliendipoole funktsionaalsus Router
Kasutame alt
üksikversiooni, nii et pärast iga renderdamist peame alt.flush()
poodides, et nad saaksid teise taotluse korral koristada. Kasutades iso
lisandmoodul on Fluxi olek järjestatud HTML-i märgistusse, et klient teaks, kust järele tulla:
// We use react-router to run the URL that is provided in routes.jsx var getHandler = function(routes, url) { var deferred = Promise.defer(); Router.run(routes, url, function (Handler) { deferred.resolve(Handler); }); return deferred.promise; }; app.use(function *(next) { yield next; // We seed our stores with data alt.bootstrap(JSON.stringify(this.locals.data || {})); var iso = new Iso(); const handler = yield getHandler(reactRoutes, this.request.url); const node = React.renderToString(React.createElement(handler)); iso.add(node, alt.flush()); this.render('layout', {html: iso.render()}); });
Kliendi poolel võtame serveri oleku ja käivitame alt
andmetega. Siis jookseme Router
ja React.render
sihtrakil, mis värskendab vajadusel serveri loodud märgistust.
Iso.bootstrap(function (state, _, container) { // Bootstrap the state from the server alt.bootstrap(state) Router.run(routes, Router.HistoryLocation, function (Handler, req) { let node = React.createElement(Handler) React.render(node, container) }) })
Armas!
Reacti ökosüsteemi juhend ei oleks täielik, kui ei mainita mõnda reaalajas eriti hästi mängivat esiotsa teeki. Need teegid tegelevad kõige tavalisemate ülesannetega, mida leidub peaaegu igas veebirakenduses: CSS-i paigutused ja konteinerid, stiilivormid ja nupud, valideerimised, kuupäevade valimine ja nii edasi. Pole mõtet ratast uuesti leiutada, kui need probleemid on juba lahendatud.
Vidistama Bootstrap raamistik on muutunud tavapäraseks, kuna sellest on tohutult abi kõigile veebiarendajatele, kes ei soovi veeta tonni aega CSS-is töötades. Eriti prototüüpide valmistamise etapis on Bootstrap hädavajalik. React rakenduses alglaadimisvõimaluste ärakasutamiseks on seda hea kasutada React-Bootstrap , mis on varustatud kena Reacti süntaksiga ja rakendab Bootstrapi jQuery pistikprogrammid uuesti, kasutades kohalikke React komponente. Saadud kood on napisõnaline ja hõlpsasti mõistetav:
Link Link Action Another action Something else here Separated link
Ise ma ei pääse tundest, et just selline HTML oleks pidanud alati olema.
Kui soovite Webpackiga kasutada allikat Bootstrap, kaaluge selle kasutamist vähem laadur või bootstrap-sass-laadur , olenevalt eelprotsessorist, mida soovite. See võimaldab teil hõlpsasti kohandada, milliseid Bootstrapi komponente kaasata, ja lubab oma CSS-koodis kasutada ka globaalseid muutujaid LESS või SASS.
Reageeri ruuter on muutunud reageerimisel de facto marsruutimise standardiks. See võimaldab sisestatud marsruutimist, ümbersuunamiste tuge, mängib kenasti isomorfse renderdusega ja sellel on lihtne JSX-põhine süntaks:
Link
React Router pakub ka About Users
komponent, mida saate oma rakenduses navigeerimiseks kasutada, määrates ainult marsruudi nime:
active
React-Bootstrapiga integreerimiseks on olemas isegi teek, nii et kui kasutate Bootstrapi komponente ja teil pole tahtmist About Users
klassi neile pidevalt käsitsi, saate kasutada reageeri-ruuter-alglaadur ja kirjutage kood nii:
import Formsy from 'formsy-react'; import {Input} from 'formsy-react-components'; export default class FormsyForm extends React.Component { enableButton() { this.setState({canSubmit: true}); } disableButton() { this.setState({canSubmit: true}); } submit(model) { FormActions.saveEmail(model.email); } render() { return ( Submit )} }
Täiendav seadistamine pole vajalik. Aktiivsed lingid hoolitsevad ise.
Vormidega töötamine võib olla tüütu, nii et palume abi vormireaktsioon raamatukogu, mis aitab meil hallata valideerimisi ja andmemudeleid. Kummalisel kombel ei sisalda Formsy-Reacti teek reaalseid vormisisendeid, kuna kasutajatel soovitatakse ise kirjutada (mis on tore). Aga kui olete rahul tavalistega, siis lihtsalt kasutage vorm-reageerivad komponendid . Bootstrapi klassid on lisatud:
import Pikaday from 'react-pikaday'; import Select from 'react-select'; export default class CalendarAndTypeahead extends React.Component { constructor(props){ super(props); this.options = [ { value: 'one', label: 'One' }, { value: 'two', label: 'Two' } ]; } dateChange(date) { this.setState({date: date}); }, selectChange(selected) { this.setState({selected: selected}); }, render() { return ( )} }
Iga kasutajaliidese tööriistakomplekti koogil on kalender ja kirjutuspea. Kahjuks eemaldati need kaks komponenti Bootstrap 3-st, ilmselt seetõttu, et nad on liiga spetsialiseerunud üldotstarbelise CSS-i raamistiku jaoks. Õnneks olen suutnud leida väärilisi asendajaid reageerima-pikaday ja reageeri-vali . Olen testinud enam kui 10 raamatukogu ja need kaks tulid parimana välja. Neid on ka surmtult lihtne kasutada:
|_+_|Kui rääkida Reactist, siis seal on džungel! Siin on kaart, mis aitab teil oma teed leida. Piiksuma
Selles artiklis olen esitanud raamatukogusid ja tehnikaid, mida pean praeguse veebiarenduse juures kõige produktiivsemaks. Mõned neist on React-spetsiifilised, kuid tänu Reacti avatud olemusele on paljud neist kasutatavad ka teistes keskkondades. Tehnoloogilist arengut takistab mõnikord hirm uusima kraami ees, seega loodan, et see artikkel aitab hajutada kahtlusi Reacti, Fluxi ja ECMAScript'i uusimate funktsioonide osas.
Kui olete huvitatud, võite minu pilgu heita näidisrakendus ehitatud nende tehnoloogiate abil. Lähtekood on saadaval aadressil GitHub .
Täname lugemast!
Seotud: React.js parimad tavad ja näpunäited ApeeScape'i arendajatelt