Taip, „React“ perima front-end kūrimą. Kyla klausimas kodėl.

Atnaujinimas: Šis straipsnis dabar yra mano knygos „React.js Beyond The Basics“ dalis. Perskaitykite atnaujintą šio turinio versiją ir daugiau apie „React“ šiuo adresu: jscomplete.com/react-beyond-basics .

Štai keletas priežasčių, kodėl „React“ taip greitai išpopuliarėjo:

  • Darbas su DOM API yra sunkus. „React“ iš esmės suteikia kūrėjams galimybę dirbti su virtualia naršykle, kuri yra draugiškesnė nei tikroji naršyklė. „React“ virtuali naršyklė veikia kaip agentas tarp kūrėjo ir tikrosios naršyklės.
  • „React“ leidžia kūrėjams deklaratyviai apibūdinti savo vartotojo sąsajas ir modeliuoti tų sąsajų būseną. Tai reiškia, kad užuot sugalvoję sąsajų operacijų aprašymo veiksmus, kūrėjai tiesiog apibūdina sąsajas kaip galutinę būseną (pvz., Funkciją). Kai operacijos įvyksta su ta būsena, „React“ rūpinasi tuo remdamasi atnaujinti vartotojo sąsajas.
  • „React“ yra tik „JavaScript“, reikia išmokti labai mažą API, tereikia kelių funkcijų ir kaip jomis naudotis. Po to jūsų „JavaScript“ įgūdžiai padaro jus geresniu „React“ kūrėju. Nėra kliūčių patekti. „JavaScript“ kūrėjas gali tapti produktyviu „React“ kūrėju per kelias valandas.

Bet tai yra daug daugiau nei tik tai. Pabandykime aptarti visas augančio „React“ populiarumo priežastis. Viena iš priežasčių yra jos virtualusis DOM („React“ suderinimo algoritmas). Mes pateiksime pavyzdį, kuris parodys faktinę tokio algoritmo turėjimo vertę jūsų komandai.

Oficialiame „React“ apibrėžime teigiama, kad tai yra „ JavaScript“ biblioteka, skirta kurti vartotojo sąsajas . Svarbu suprasti dvi skirtingas šio apibrėžimo dalis:

  1. „React“ yra „ JavaScript“ biblioteka . Tai nėra pagrindas. Tai nėra išsamus sprendimas, todėl norint sukurti bet kokį sprendimą, dažnai reikės naudoti daugiau bibliotekų su „React“. „React“ nieko neprisiima apie jokias visas tirpalo dalis. Jis orientuotas tik į vieną dalyką ir į tai, kad labai gerai tai darai.
  2. Tai, ką „React“ daro tikrai gerai, yra antroji apibrėžimo dalis: kurti vartotojo sąsajas . Vartotojo sąsaja yra viskas, ką mes pateikiame prieš vartotojus, kad jie sąveikautų su mašina. Vartotojo sąsajos yra visur, nuo paprastų mikrobangų mygtukų iki kosminio maršruto prietaisų skydelio. Jei įrenginys, kurį bandome susieti, gali suprasti „JavaScript“, galime naudoti „React“, kad apibūdintume jo vartotojo sąsają.

Kadangi žiniatinklio naršyklės supranta „JavaScript“, galime naudoti „React“, kad apibūdintume žiniatinklio vartotojo sąsajas. Man patinka naudoti žodį apibūdinti , nes čia tai, ką mes iš esmės daryti su Pareikšk, mes tiesiog pasakyti, ko mes norime ir reaguoti statys faktinius vartotojo sąsajas, mūsų vardu, į interneto naršyklę. Be „React“ ar panašių bibliotekų turėtume rankiniu būdu kurti vartotojo sąsajas su vietinėmis žiniatinklio API ir „JavaScript“.

Išgirdę teiginį, kad „Reakcija yra deklaratyvi“, būtent tai ir reiškia, apibūdiname Vartotojo sąsajas su „React“ ir pasakome, ko norime (o ne kaip tai padaryti). „React“ pasirūpins „kaip“ ir išvers mūsų deklaratyvius aprašymus (kuriuos rašome „React“ kalba) į tikras naršyklės vartotojo sąsajas. „React“ dalijasi šia paprasta deklaravimo jėga su pačiu HTML, tačiau su „React“ turime būti deklaratyvūs HTML sąsajoms, kurios atspindi dinaminius duomenis, o ne tik statinius duomenis.

„React“ turi tris pagrindines populiarumo skatinančias dizaino koncepcijas:

1 - Daugkartinių, sudedamų ir būsenos komponentų naudojimas

„React“ aprašome vartotojo sąsajas naudodami komponentus. Komponentus galite laikyti paprastomis funkcijomis (bet kuria programavimo kalba). Mes iškviečiame funkcijas su tam tikru įėjimu ir jos suteikia mums tam tikrą išvestį. Mes galime pakartotinai naudoti funkcijas, jei reikia, ir sudaryti didesnes funkcijas iš mažesnių.

Komponentai yra visiškai vienodi; jų įvestį vadiname „ypatybėmis“ ir „būsena“, o komponento išvestis yra vartotojo sąsajos aprašas (kuris yra panašus į naršyklių HTML). Mes galime pakartotinai naudoti vieną komponentą keliose vartotojo sąsajose, o komponentuose gali būti kitų komponentų.

Skirtingai nuo grynų funkcijų, visiškas „React“ komponentas gali turėti privačią būseną duomenims laikyti, kurie laikui bėgant gali pasikeisti.

2 - reaktyvių atnaujinimų pobūdis

React vardas yra paprastas šios sąvokos paaiškinimas. Keičiant komponento (įvesties) būseną, keičiasi ir jo atstovaujama vartotojo sąsaja (išvestis). Šis vartotojo sąsajos aprašo pakeitimas turi atsispindėti įrenginyje, su kuriuo dirbame.

Naršyklėje turime atkurti HTML rodinius dokumento objekto modelyje (DOM). Naudojant „React“ nereikia rūpintis, kaip atspindėti šiuos pakeitimus, ar net valdyti, kada atlikti pakeitimus naršyklėje; „React“ tiesiog reaguos į būsenos pokyčius ir prireikus automatiškai atnaujins DOM.

3 - virtualus vaizdų atvaizdavimas atmintyje

Naudodami „React“ mes rašome HTML naudodami „JavaScript“. Mes remiamės „JavaScript“ galia generuoti HTML, kuris priklauso nuo kai kurių duomenų, o ne tobuliname HTML, kad jis veiktų su tais duomenimis. HTML patobulinimas yra tai, ką paprastai daro kitos „JavaScript“ sistemos. Pavyzdžiui, „Angular“ išplečia HTML su tokiomis funkcijomis kaip kilpos, sąlyginiai ir kt.

Kai iš serverio gauname tik duomenis (fone, su AJAX), mums reikia daugiau nei HTML, kad galėtume dirbti su tais duomenimis. HTML generavimui naudojamas arba patobulintas HTML, arba pačios „JavaScript“ galimybės. Abu požiūriai turi privalumų ir trūkumų. „React“ apima pastarąjį, argumentuodamas tuo, kad pranašumai yra stipresni nei trūkumai.

Tiesą sakant, yra vienas pagrindinis pranašumas, kuris gali būti tinkamas šiam požiūriui; naudojant „JavaScript“ HTML atvaizdavimui, „React“ gali lengvai išlaikyti virtualų HTML vaizdą atmintyje (kuris paprastai žinomas kaip „Virtual DOM“ ). „React“ naudoja virtualųjį DOM, kad iš pradžių būtų pateiktas HTML medis, o tada kiekvieną kartą pasikeitus būsenai ir gaunant naują HTML medį, kurį reikia perkelti į naršyklės DOM, užuot rašius visą naują medį, „React“ rašys tik skirtumas tarp naujo medžio ir ankstesnio medžio (kadangi „React“ atmintyje yra abu medžiai). Šis procesas yra žinomas kaip medžių susitaikymas , ir aš manau, kad tai geriausia, kas nutiko kuriant žiniatinklį nuo AJAX!

Kitame pavyzdyje mes sutelksime dėmesį į šią paskutinę koncepciją ir pamatysime paprastą praktinį medžių susitaikymo proceso ir didelio jo skirtumo pavyzdį. Mes du kartus parašysime tą patį HTML pavyzdį, pirmiausia naudodami vietines žiniatinklio API ir „vanilla JavaScript“, tada pamatysime, kaip tą patį HTML medį apibūdinti naudojant „React“.

Norėdami sutelkti dėmesį tik į šią paskutinę koncepciją, nenaudosime komponentų, o naudodami „JavaScript“ laikmatį mes pasityčiosime iš būsenos keitimo operacijos. Mes taip pat nesiruošiame naudoti JSX, nors naudojant JSX bus kur kas paprastesnis kodas. Rašydamas „React“ visą laiką naudoju „JSX“, bet, tikėdamasis, kad šiame pavyzdyje dirbdamas tiesiogiai su „React API“, tikimės, kad suprasite šią koncepciją kur kas geriau.

React'o susitaikymo algoritmo pavyzdys

Norėdami sekti šį pavyzdį, jums reikia naršyklės ir kodo redaktoriaus. Jūs iš tikrųjų galite naudoti internetinę kodavimo žaidimų aikštelę, bet aš naudosiu vietinius failus ir išbandysiu juos tiesiogiai naršyklėje (mums nereikia žiniatinklio serverio):

Šį pavyzdį pradėsime nuo nulio. Sukurkite naują katalogą ir paleiskite ten savo mėgstamą redaktorių:

mkdir react-democd react-demoatom .

Sukurkite index.htmlfailą tame kataloge ir įdėkite standartinį HTML šabloną. Įtraukite į tą šabloną script.jsfailą ir įdėkite console.logteiginį į tą scenarijų, kad patikrintumėte, ar įtraukimas veikia:

    React Demo     

index.htmlNaršyklėje atidarykite failą ir įsitikinkite, kad be problemų matote tuščią šabloną ir skirtuke „Console dev-tools“ galite pamatyti console.logbandomąjį pranešimą, kurį įdėjote script.js:

open index.html # On Mac explorer index.html # On Windows

Now, let’s bring in the React library itself, which we can include from the Reactjs website. Copy both the react and react-dom scripts, and include them in index.html:

We’re including two different scripts here for an important reason: The React library itself can be used without a browser. To use React with a browser, we need the ReactDOM library.

When we refresh the browser now, we should see both React and ReactDOM available on the global scope:

With this simple setup, we can now access both React and ReactDOM APIs, and of course, we also have access to the native Web APIs and JavaScript which we are going to use first.

To insert HTML dynamically in the browser we can simply use pure JavaScript and the DOM Web API itself. Let’s create a div element to host our JavaScript HTML content and give it the id "js". In the body element of index.html, right before the script tag, add:

Now in script.js, let's grab this new div element by its id and put it in a constant. Let's name this constant jsContainer. We can use document.getElementById to grab the div from HTML:

jsContainer.innerHTML = ` Hello JS `;

To control the content of this div, we can use the innerHTML setter call on the div element directly. We can use this call to supply any HTML template that we want inserted in the DOM. Let's insert a div element with a class of "demo" and the string "Hello JS" as its content:

jsContainer.innerHTML = ` Hello JS `;ReactDOM.render( /* TODO: React's version of the HTML template */, reactContainer )

Make sure this works in the browser. You should see the “Hello JS” line on the screen now.

This demo div is our User Interface so far. It’s a very simple one. We just output a text for the user to see.

Both document.getElementById and element.innerHTML are actually part of the native DOM Web API. We are communicating with the browser directly here using the supported APIs of the Web platform. When we write React code, however, we use the React API instead, and we let React communicate with the browser using the DOM Web API.

React acts like our agent for the browser, and we mostly need to communicate with just React, our agent, and not the browser itself. I say mostly because there are cases where we still need to communicate with the browser, but those are rare.

To create the exact same User Interface that we have so far but with React API this time, let’s create another div element and give it an id of "react". In index.html, right under the div#js element, add:

Now, in script.js, create a new container constant for the new div:

const reactContainer = document.getElementById("react");

This container will be the only call we make to the native web API. ReactDOM needs this container to know where to host our application in the DOM.

With the react container identified, we can now use the ReactDOM library to render React's version of the HTML template to this container:

ReactDOM.render( /* TODO: React's version of the HTML template */, reactContainer )

What we’re going to do next is your first milestone in truly understanding the React library. Remember when I told you that with React we write HTML using JavaScript? This is exactly what we are going to do next.

To write our simple HTML User Interface, we are going to use JavaScript calls to React API, and by the end of the example you’ll have a better picture about the reason for doing so.

Instead of working with strings (as we did in the native JavaScript example above), in React, we work with objects. Any HTML string will be represented as an object using a React.createElement call (which is the core function in the React API).

Here’s the equivalent HTML User Interface we have so far with React:

ReactDOM.render( React.createElement( "div", { className: "demo" }, "Hello React" ), reactContainer );

React.createElement has many arguments:

  • The first argument is the HTML tag, which is div in our example.
  • The second argument is an object that represents any attributes we want this tag to have. To match the native JS example we used { className: "demo" } which translates to class="demo". Note how we used className instead of class in the attributes because with React it's all JavaScript that matches the Web API, not HTML itself.
  • The third argument is the content of the element. We’ve put a “Hello React” string in there.

We can test this now. The browser should render both “Hello JS” and “Hello React”. Let’s style the demo divs as a box, using this CSS, just so that we can visually split the screen. In index.html:

 .demo { border: 1px solid #ccc; margin: 1em; padding: 1em; } 

We now have two nodes, one being controlled with the DOM Web API directly, and another being controlled with the React API (which in turn uses the DOM Web API). The only major difference between the ways we are building these two nodes in the browser is that in the JS version we used a string to represent the content, while in the React version we used pure JavaScript calls and represented the content with an object instead of a string.

No matter how complicated the HTML User Interface is going to get, when using React, every HTML element will be represented with a JavaScript object using a React.createElement call.

Let’s now add some more features to our simple User Interface. Let’s add a text box to read input from the user.

To nest elements in our HTML template, it’s straight forward in the JS version because it’s just HTML. For example, to make the demo div render an element, we simply add it to the content:

jsContainer.innerHTML = ` Hello JS `;

We can do the same with React by adding more arguments after the 3rd argument for React.createElement. To match what we did in the native JS example, we can add a 4th argument that is another React.createElement call that renders an input element (remember, every HTML element is an object):

ReactDOM.render( React.createElement( "div", { className: "demo" }, "Hello React", React.createElement("input") ), reactContainer );

At this point, if you’re questioning what we’re doing and thinking “this is complicating a simple process”, you are totally right! But there is a very good reason for what we’re doing. Keep reading.

Let’s also render a timestamp in both versions. In the JS version, let’s put the timestamp in a paragraph element. We can use a call to new Date() to display a simple timestamp:

jsContainer.innerHTML = ` Hello JS  

${new Date()}

`;

To do the same in React, we add a 5th argument to the top-level div element. This new 5th argument is another React.createElement call, this time using a p tag, with no attributes, and the new Date() string for content:

ReactDOM.render( React.createElement( "div", { className: "demo" }, "Hello React", React.createElement("input"), React.createElement( "p", null, new Date().toString() ) ), reactContainer );

Both JS and React versions are still rendering the exact same HTML in the browser.

As you can see, so far, using React is actually a lot harder than the simple and familiar native way. What is it that React does so well that’s worth giving up the familiar HTML and having to learn a new API to write what can be simply written in HTML? The answer is not about rendering the first HTML view, it’s about what we need to do to update any existing view in the DOM.

So, let’s do an update operation on the DOM we have so far. Let’s simply make the timestamp tick every second.

We can easily repeat a JavaScript function call in a browser using the setInterval Web timer API. So, let's put all of our DOM manipulations for both JS and React versions in a function, call it render, and use it in a setInterval call to make it repeat every second.

Here’s the full final code in script.js:

const jsContainer = document.getElementById("js"); const reactContainer = document.getElementById("react"); const render = () => { jsContainer.innerHTML = ` Hello JS  

${new Date()}

`; ReactDOM.render( React.createElement( "div", { className: "demo" }, "Hello React ", React.createElement("input"), React.createElement( "p", null, new Date().toString() ) ), reactContainer ); } setInterval(render, 1000);

When we refresh the browser now, the timestamp string should be ticking every second in both versions. We are now updating our User Interface in the DOM.

This is the moment when React will potentially blow your mind. If you try to type something in the text box of the JS version, you won’t be able to. This is very much expected because we’re basically throwing away the whole DOM node on every tick and regenerating it. However, if you try to type something in the text box that’s rendered with React, you can certainly do so!

Although the whole React rendering code is within our ticking timer, React is changing only the timestamp paragraph and not the whole DOM node. This is why the text input box was not regenerated and we were able to type in it.

You can see the different ways we’re updating the DOM visually if you inspect the two DOM nodes in a Chrome dev tools elements panel. The Chrome div tools highlights any HTML elements that get updated. You’ll see how we are regenerating the whole “js” div on every tick, while React is smartly only regenerating the paragraph with the timestamp string.

React has a smart diffing algorithm that it uses to only regenerate in its DOM node what actually needs to be regenerated while it keeps everything else as is. This diffing process is possible because of React’s virtual DOM and the fact that we have a representation of our User Interface in memory (because we wrote in JavaScript).

Using the virtual DOM, React keeps the last DOM version in memory and when it has a new DOM version to take to the browser, that new DOM version will also be in memory, so React can compute the difference between the new and the old versions (in our case, the difference is the timestamp paragraph).

React will then instruct the browser to update only the computed diff and not the whole DOM node. No matter how many times we regenerate our interface, React will take to the browser only the new “partial” updates.

Šis metodas yra ne tik daug efektyvesnis, bet ir pašalina didelį sudėtingumą, kaip mes galvojame apie vartotojo sąsajų atnaujinimą. Jei „React“ atliks visus skaičiavimus, ar turėtume atnaujinti DOM, ar ne, galime sutelkti dėmesį į savo duomenis (būseną) ir jų vartotojo sąsajos apibūdinimo būdą.

Tada, jei reikia, tvarkome savo duomenų atnaujinimus, nesijaudindami veiksmų, reikalingų šiems naujinimams atspindėti tikrojoje vartotojo sąsajoje naršyklėje (nes žinome, kad „React“ atliks būtent tai ir tai padarys efektyviai!)

Ačiū, kad skaitėte! Čia galite peržiūrėti mano demonstracinės versijos šaltinio kodą ir čia rodomą demonstracinę versiją.

Mokotės reakciją ar mazgą? Patikrinkite mano knygas:

  • Sužinokite React.js kurdami žaidimus
  • „Node.js“ už pagrindų