Ja, React übernimmt die Front-End-Entwicklung. Die Frage ist warum.

Update: Dieser Artikel ist jetzt Teil meines Buches „React.js Beyond The Basics“. Lesen Sie die aktualisierte Version dieses Inhalts und mehr über React unter jscomplete.com/react-beyond-basics .

Hier sind einige Gründe, warum React so schnell so beliebt geworden ist:

  • Die Arbeit mit der DOM-API ist schwierig. Mit React können Entwickler grundsätzlich mit einem virtuellen Browser arbeiten, der benutzerfreundlicher ist als der reale Browser. Der virtuelle Browser von React fungiert als Agent zwischen dem Entwickler und dem realen Browser.
  • Mit React können Entwickler ihre Benutzeroberflächen deklarativ beschreiben und den Status dieser Schnittstellen modellieren. Dies bedeutet, dass Entwickler anstelle von Schritten zur Beschreibung von Transaktionen auf Schnittstellen nur die Schnittstellen als Endzustand (wie eine Funktion) beschreiben. Wenn Transaktionen in diesem Zustand stattfinden, übernimmt React die Aktualisierung der Benutzeroberflächen auf dieser Grundlage.
  • React ist nur JavaScript, es gibt eine sehr kleine API zu lernen, nur ein paar Funktionen und wie man sie benutzt. Danach machen Sie Ihre JavaScript-Kenntnisse zu einem besseren React-Entwickler. Es gibt keine Eintrittsbarrieren. Ein JavaScript-Entwickler kann in wenigen Stunden ein produktiver React-Entwickler werden.

Aber es steckt noch viel mehr dahinter. Versuchen wir, alle Gründe für die zunehmende Beliebtheit von React zu ermitteln. Ein Grund ist das virtuelle DOM (React's Abstimmungsalgorithmus). Wir werden ein Beispiel durcharbeiten, um den tatsächlichen praktischen Wert eines solchen Algorithmus zu zeigen, der Ihnen zur Verfügung steht.

Die offizielle Definition von React besagt, dass es sich um eine JavaScript-Bibliothek zum Erstellen von Benutzeroberflächen handelt . Es ist wichtig, die zwei verschiedenen Teile dieser Definition zu verstehen:

  1. React ist eine JavaScript-Bibliothek . Es ist kein Rahmen. Es ist keine vollständige Lösung, und wir müssen häufig mehr Bibliotheken mit React verwenden, um eine Lösung zu erstellen. React setzt in keiner vollständigen Lösung etwas über die anderen Teile voraus. Es konzentriert sich nur auf eine Sache und darauf, diese Sache sehr gut zu machen.
  2. Was React wirklich gut macht, ist der zweite Teil der Definition: Erstellen von Benutzeroberflächen . Eine Benutzeroberfläche ist alles, was wir den Benutzern vorlegen, damit sie mit einer Maschine interagieren können. Benutzeroberflächen gibt es überall, von den einfachen Tasten einer Mikrowelle bis zum Armaturenbrett eines Space Shuttles. Wenn das Gerät, für das wir eine Schnittstelle herstellen möchten, JavaScript verstehen kann, können wir mit React eine Benutzeroberfläche dafür beschreiben.

Da Webbrowser JavaScript verstehen, können wir React verwenden, um Webbenutzeroberflächen zu beschreiben. Ich verwende hier gerne das Wort " beschreiben" , weil wir das im Grunde mit React tun. Wir sagen ihm einfach, was wir wollen, und React erstellt in unserem Auftrag die eigentlichen Benutzeroberflächen im Webbrowser. Ohne React oder ähnliche Bibliotheken müssten wir Benutzeroberflächen mit nativen Web-APIs und JavaScript manuell erstellen.

Wenn Sie die Aussage hören, dass "React deklarativ ist", ist dies genau das, was es bedeutet. Wir beschreiben Benutzeroberflächen mit React und sagen ihm, was wir wollen (nicht wie es geht). React kümmert sich um das „Wie“ und übersetzt unsere deklarativen Beschreibungen (die wir in der React-Sprache schreiben) in tatsächliche Benutzeroberflächen im Browser. React teilt diese einfache deklarative Kraft mit HTML selbst, aber mit React können wir deklarativ für HTML-Schnittstellen sein, die dynamische Daten darstellen, nicht nur statische Daten.

React hat drei Hauptdesignkonzepte, die seine Popularität steigern:

1 - Die Verwendung von wiederverwendbaren, zusammensetzbaren und zustandsbehafteten Komponenten

In React beschreiben wir Benutzeroberflächen mithilfe von Komponenten. Sie können sich Komponenten als einfache Funktionen vorstellen (in jeder Programmiersprache). Wir rufen Funktionen mit einer Eingabe auf und sie geben uns eine Ausgabe. Wir können Funktionen nach Bedarf wiederverwenden und größere Funktionen aus kleineren zusammensetzen.

Komponenten sind genau gleich; Wir nennen ihre Eingabe "Eigenschaften" und "Status", und eine Komponentenausgabe ist eine Beschreibung einer Benutzeroberfläche (die HTML für Browser ähnelt). Wir können eine einzelne Komponente in mehreren Benutzeroberflächen wiederverwenden, und Komponenten können andere Komponenten enthalten.

Im Gegensatz zu reinen Funktionen kann eine vollständige React-Komponente jedoch einen privaten Status haben, in dem Daten gespeichert werden, die sich im Laufe der Zeit ändern können.

2 - Die Art der reaktiven Updates

Der Name von React ist die einfache Erklärung für dieses Konzept. Wenn sich der Status einer Komponente (der Eingabe) ändert, ändert sich auch die Benutzeroberfläche, die sie darstellt (die Ausgabe). Diese Änderung in der Beschreibung der Benutzeroberfläche muss sich in dem Gerät widerspiegeln, mit dem wir arbeiten.

In einem Browser müssen wir die HTML-Ansichten im Document Object Model (DOM) neu generieren. Mit React müssen wir uns keine Gedanken darüber machen, wie diese Änderungen berücksichtigt werden sollen, und müssen nicht einmal verwalten, wann Änderungen am Browser vorgenommen werden sollen. React reagiert einfach auf Statusänderungen und aktualisiert das DOM bei Bedarf automatisch.

3 - Die virtuelle Darstellung von Ansichten im Speicher

Mit React schreiben wir HTML mit JavaScript. Wir verlassen uns auf die Leistungsfähigkeit von JavaScript, um HTML zu generieren, das von einigen Daten abhängt, anstatt HTML zu verbessern, damit es mit diesen Daten funktioniert. Das Verbessern von HTML ist das, was andere JavaScript-Frameworks normalerweise tun. Angular erweitert beispielsweise HTML um Funktionen wie Schleifen, Bedingungen und andere.

Wenn wir nur die Daten vom Server empfangen (im Hintergrund mit AJAX), benötigen wir mehr als HTML, um mit diesen Daten zu arbeiten. Entweder wird ein erweitertes HTML verwendet oder es wird die Leistung von JavaScript selbst verwendet, um das HTML zu generieren. Beide Ansätze haben Vor- und Nachteile. React umfasst letzteres mit dem Argument, dass die Vorteile stärker sind als die Nachteile.

Tatsächlich gibt es einen großen Vorteil, der für diesen Ansatz von sich aus sprechen kann. Die Verwendung von JavaScript zum Rendern von HTML erleichtert React das Speichern einer virtuellen Darstellung von HTML im Speicher (allgemein bekannt als The Virtual DOM ). React verwendet das virtuelle DOM, um einen HTML-Baum zuerst virtuell zu rendern. Jedes Mal, wenn sich ein Status ändert und wir einen neuen HTML-Baum erhalten, der in das DOM des Browsers übernommen werden muss, anstatt den gesamten neuen Baum zu schreiben, schreibt React nur den Unterschied zwischen dem neuen Baum und dem vorherigen Baum (da React beide Bäume im Speicher hat). Dieser Prozess ist als Tree Reconciliation bekannt und ich denke, es ist das Beste, was in der Webentwicklung seit AJAX passiert ist!

Im folgenden Beispiel konzentrieren wir uns auf dieses letzte Konzept und sehen ein einfaches praktisches Beispiel für den Baumabgleichsprozess und den großen Unterschied, den er macht. Wir werden dasselbe HTML-Beispiel zweimal schreiben, zuerst mit nativen Web-APIs und Vanille-JavaScript, und dann werden wir sehen, wie derselbe HTML-Baum mit React beschrieben wird.

Um uns nur auf dieses letzte Konzept zu konzentrieren, werden wir keine Komponenten verwenden und eine Statusänderungsoperation mit einem JavaScript-Timer verspotten. Wir werden JSX auch nicht verwenden, obwohl die Verwendung von JSX den Code viel einfacher macht. Ich verwende JSX die ganze Zeit, wenn ich React schreibe, aber wenn Sie in diesem Beispiel direkt mit der React-API arbeiten, werden Sie dieses Konzept hoffentlich viel besser verstehen.

Beispiel für den Abstimmungsalgorithmus von React

Um diesem Beispiel folgen zu können, benötigen Sie einen Browser und einen Code-Editor. Sie können tatsächlich einen Online-Codierungsspielplatz verwenden, aber ich verwende lokale Dateien und teste sie direkt in einem Browser (wir benötigen keinen Webserver):

Wir werden dieses Beispiel von vorne beginnen. Erstellen Sie ein neues Verzeichnis und starten Sie dort Ihren Lieblingseditor:

mkdir react-democd react-demoatom .

Erstellen Sie eine index.htmlDatei in diesem Verzeichnis und fügen Sie dort eine Standard-HTML-Vorlage ein. Fügen Sie in diese Vorlage eine script.jsDatei ein und fügen Sie eine console.logAnweisung in dieses Skript ein, um zu testen, ob das Include funktioniert:

    React Demo     

Öffnen Sie die index.htmlDatei in Ihrem Browser und stellen Sie sicher, dass Sie die leere Vorlage ohne Probleme sehen können und dass Sie auf der Registerkarte Console dev-tools die von console.logIhnen eingegebene Testnachricht sehen können 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.

Not only is this method a lot more efficient, but it also removes a big layer of complexity for the way we think about updating User Interfaces. Having React do all the computations about whether we should update the DOM or not enables us to focus on thinking about our data (state) and the way to describe a User Interface for it.

We then manage the updates on our data as needed without worrying about the steps needed to reflect these updates on the actual User Interface in the browser (because we know React will do exactly that and it will do that in an efficient way!)

Thanks for reading! You can view the source code of my demo here, and you can see the demo running here.

Learning React or Node? Checkout my books:

  • Learn React.js by Building Games
  • Node.js Beyond the Basics