Ja, React overtager front-end-udvikling. Spørgsmålet er hvorfor.

Opdatering: Denne artikel er nu en del af min bog "React.js Beyond The Basics". Læs den opdaterede version af dette indhold og mere om React på jscomplete.com/react-beyond-basics .

Her er et par grunde til, at React er blevet så populært så hurtigt:

  • Det er svært at arbejde med DOM API. React giver grundlæggende udviklere mulighed for at arbejde med en virtuel browser, der er mere venlig end den rigtige browser. React's virtuelle browser fungerer som en agent mellem udvikleren og den rigtige browser.
  • React gør det muligt for udviklere at erklærende beskrive deres brugergrænseflader og modellere tilstanden for disse grænseflader. Dette betyder i stedet for at komme med trin til at beskrive transaktioner på grænseflader, udviklere beskriver bare grænsefladerne i form af en endelig tilstand (som en funktion). Når transaktioner sker med denne tilstand, tager React sig af opdatering af brugergrænsefladerne baseret på det.
  • React er bare JavaScript, der er en meget lille API at lære, blot et par funktioner og hvordan man bruger dem. Derefter er dine JavaScript-færdigheder det, der gør dig til en bedre React-udvikler. Der er ingen hindringer for adgang. En JavaScript-udvikler kan blive en produktiv React-udvikler om få timer.

Men der er meget mere end bare det. Lad os forsøge at dække alle årsagerne bag React's stigende popularitet. En af årsagerne er dens virtuelle DOM (React's afstemningsalgoritme). Vi gennemgår et eksempel for at vise den faktiske praktiske værdi af at have en sådan algoritme på din kommando.

Reacts officielle definition siger, at det er et JavaScript-bibliotek til opbygning af brugergrænseflader . Det er vigtigt at forstå de to forskellige dele af denne definition:

  1. React er et JavaScript-bibliotek . Det er ikke en ramme. Det er ikke en komplet løsning, og vi bliver ofte nødt til at bruge flere biblioteker med React for at danne enhver løsning. React antager ikke noget om de andre dele i nogen fuld opløsning. Det fokuserer kun på én ting og på at gøre den ting meget godt.
  2. Det, som React gør rigtig godt, er den anden del af definitionen: opbygning af brugergrænseflader . En brugergrænseflade er alt, hvad vi stiller foran brugerne for at få dem til at interagere med en maskine. Brugergrænseflader er overalt, fra de enkle knapper på en mikrobølgeovn til instrumentbrættet på en rumfærge. Hvis den enhed, vi prøver at grænseflade, kan forstå JavaScript, kan vi bruge React til at beskrive en brugergrænseflade til det.

Da webbrowsere forstår JavaScript, kan vi bruge React til at beskrive webbrugergrænseflader. Jeg kan godt lide at bruge det ord, der beskrives her, for det er det, vi grundlæggende gør med React, vi fortæller det bare, hvad vi vil, og React vil bygge de faktiske brugergrænseflader på vores vegne i webbrowseren. Uden React eller lignende biblioteker skal vi manuelt oprette brugergrænseflader med native Web API'er og JavaScript.

Når du hører udsagnet om, at “React is declarative,” det er præcis hvad det betyder, beskriver vi brugergrænseflader med React og fortæller det, hvad vi vil (ikke hvordan man gør det). React tager sig af “hvordan” og oversætter vores deklarative beskrivelser (som vi skriver på React-sproget) til faktiske brugergrænseflader i browseren. React deler denne enkle deklarative magt med HTML selv, men med React bliver vi deklarative for HTML-grænseflader, der repræsenterer dynamiske data, ikke kun statiske data.

React har tre hoveddesignkoncepter, der driver dens popularitet:

1 - Brug af genanvendelige, komponerbare og statefulde komponenter

I React beskriver vi brugergrænseflader ved hjælp af komponenter. Du kan tænke på komponenter som enkle funktioner (på ethvert programmeringssprog). Vi kalder funktioner med noget input, og de giver os noget output. Vi kan genbruge funktioner efter behov og komponere større funktioner fra mindre.

Komponenter er nøjagtigt de samme; vi kalder deres input "egenskaber" og "tilstand", og en komponentoutput er en beskrivelse af en brugergrænseflade (som svarer til HTML for browsere). Vi kan genbruge en enkelt komponent i flere brugergrænseflader, og komponenter kan indeholde andre komponenter.

I modsætning til rene funktioner kan en fuld React-komponent dog have en privat tilstand til at indeholde data, der kan ændre sig over tid.

2 - Arten af ​​reaktive opdateringer

React's navn er den enkle forklaring på dette koncept. Når tilstanden for en komponent (input) ændres, ændres også brugergrænsefladen, den repræsenterer (output). Denne ændring i beskrivelsen af ​​brugergrænsefladen skal afspejles i den enhed, vi arbejder med.

I en browser er vi nødt til at gendanne HTML-visningerne i Document Object Model (DOM). Med React behøver vi ikke bekymre os om, hvordan vi reflekterer disse ændringer eller endda styre, hvornår vi skal foretage ændringer i browseren; Reager vil simpelthen reagere på de tilstandsændringer og automatisk opdatere DOM efter behov.

3 - Den virtuelle gengivelse af synspunkter i hukommelsen

Med React skriver vi HTML ved hjælp af JavaScript. Vi er afhængige af JavaScript-styrken til at generere HTML, der afhænger af nogle data, snarere end at forbedre HTML for at få det til at fungere med disse data. Forbedring af HTML er, hvad andre JavaScript-rammer normalt gør. For eksempel udvider Angular HTML med funktioner som sløjfer, betingede og andre.

Når vi kun modtager data fra serveren (i baggrunden med AJAX), har vi brug for noget mere end HTML for at arbejde med disse data. Det bruger enten en forbedret HTML eller bruger selve JavaScript til at generere HTML. Begge tilgange har fordele og ulemper. React omfavner sidstnævnte med argumentet om, at fordelene er stærkere end ulemperne.

Der er faktisk en stor fordel, der i sig selv kan begrunde denne fremgangsmåde; Brug af JavaScript til gengivelse af HTML gør det let for React at gemme en virtuel gengivelse af HTML i hukommelsen (som almindeligvis er kendt som The Virtual DOM ). React bruger Virtual DOM til at gengive et HTML-træ næsten først, og derefter, hver gang en tilstand ændres, og vi får et nyt HTML-træ, der skal føres til browserens DOM, i stedet for at skrive det helt nye træ, vil React kun skrive forskellen mellem det nye træ og det forrige træ (da React har begge træer i hukommelsen). Denne proces er kendt som Tree Reconciliation , og jeg tror, ​​det er den bedste ting, der er sket i Webudvikling siden AJAX!

I det følgende eksempel vil vi fokusere på dette sidste koncept og se et simpelt praktisk eksempel på træafstemningsprocessen og den store forskel, det gør. Vi skriver det samme HTML-eksempel to gange, først ved hjælp af indfødte web-API'er og vanilje-JavaScript, og så ser vi, hvordan vi beskriver det samme HTML-træ med React.

For rent at fokusere på dette sidste koncept bruger vi ikke komponenter, og vi vil spotte en tilstandsændringsoperation ved hjælp af en JavaScript-timer. Vi vil heller ikke bruge JSX, selvom brug af JSX vil give en meget enklere kode. Jeg bruger JSX hele tiden, når jeg skriver React, men at arbejde med React API direkte i dette eksempel vil forhåbentlig få dig til at forstå dette koncept meget bedre.

React's eksempel på afstemningsalgoritme

For at følge dette eksempel har du brug for en browser og en kodeditor. Du kan faktisk bruge en online kodende legeplads, men jeg bruger lokale filer og tester dem direkte i en browser (vi har ikke brug for en webserver):

Vi starter dette eksempel fra bunden. Opret en ny mappe, og start din yndlingseditor der:

mkdir react-democd react-demoatom .

Opret en index.htmlfil i den mappe, og læg en standard HTML-skabelon derinde. Inkluder i den skabelon en script.jsfil og læg en console.logerklæring i dette script for at teste, at inkluderingen fungerer:

    React Demo     

Åbn index.htmlfilen i din browser, og sørg for at du kan se den tomme skabelon uden problemer, og at du kan se den console.logtestmeddelelse, du har lagt i, i fanen Konsoludviklingsværktøjer 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.

Ikke kun er denne metode meget mere effektiv, men den fjerner også et stort lag af kompleksitet for den måde, vi tænker på at opdatere brugergrænseflader. Efter at have React foretaget alle beregningerne om, hvorvidt vi skal opdatere DOM eller ej, kan vi fokusere på at tænke på vores data (tilstand) og hvordan vi beskriver en brugergrænseflade til den.

Vi administrerer derefter opdateringerne på vores data efter behov uden at bekymre os om de nødvendige trin for at afspejle disse opdateringer i den aktuelle brugergrænseflade i browseren (fordi vi ved, at React vil gøre præcis det, og det vil gøre det på en effektiv måde!)

Tak for læsningen! Du kan se kildekoden til min demo her, og du kan se demoen køre her.

Learning React eller Node? Tjek mine bøger:

  • Lær React.js ved at bygge spil
  • Node.js ud over det grundlæggende