Výhody manipulace s DOM pomocí knihovny React

Miroslav Uhlíř
4 min readNov 19, 2018

--

V tomto článku se podíváme na výhody Reactu. Převážně se zaměříme na virtuální DOM. Vytvoříme ukázku, ve které názorně uvidíme rozdíl mezi aktualizací DOM přes Web API a pomocí Reactu.

Document Object Model

DOM (Document Object Model) je stromová reprezentace dokumentu tvořena uzly. V případě HTML jsou jednotlivé uzly elementy, které mohou mít další poduzly. Každý uzel je objekt, který má property a metody. Pomocí Web API tyto metody voláme a upravujeme tak DOM. U webové stránky k manipulaci s DOM používáme JavaScript. Nevýhodou DOM je, že není primárně určen pro UI (uživatelská rozhraní). Manipulaci s DOM nám může výrazně ulehčit například knihovna React.

Výhody Reactu

React je populární knihovna vytvořená Facebookem pro tvorbu UI. Mezi hlavní vlastnosti Reactu patří znovu použitelné komponenty, kompozice, jednosměrné plynutí dat a virtuální DOM, který je abstrakcí skutečného DOM.

Elementy a komponenty

Uživatelské rozhraní vytváříme pomocí komponent. React komponenta může být buď třída nebo funkce. Komponenta se skládá z elementů. Komponenty mohou v sobě obsahovat další komponenty. Z menších komponent můžeme poskládat složitější komponenty.

Ukázka nejjednodušší komponenty v Reactu pomocí funkce

function Welcome() {
return <h1 className=”headline”>Hello!</h1>;
}

Funkce vytvoří element <h1>Hello!</h1>. Návratová hodnota komponenty je vždy element. React používá JSX, které na první pohled připomíná HTML. Nejedná se však o HTML tagy. JSX je syntaktický cukr nad JavaScriptem. HTML v Reactu generujeme pomocí JavaScriptu. Elementy jsou JavaScriptové objekty.

Ukázka předchozí funkce po převodu z JSX na JavaScript

function Welcome() {
return React.createElement(
“h1”,
{ className: “headline” },
“Hello!”
);
}

React vytvoří tento JavaScriptový objekt ve virtuálním DOM

{
type: “h1”,
props: {
className: “headline”,
children: [
“Hello!”]}


}

U nadpisu h1 nemůžeme použít slovo class, protože je to rezervované slovo v JavaScriptu. Musíme použít slovo className.

Deklarativní UI

React umožňuje snadnější manipulaci s DOM. UI zde popisujeme deklarativně. V Reactu popíšeme, co chceme vykreslit a už se nestaráme o to, jakým způsobem vykreslení React provede. V Reactu vůbec nepoužíváme metody jako append child nebo destroy child. Nemanipulujeme přímo se skutečným DOM pomocí Web API. Místo toho používáme API Reactu, které upravuje virtuální DOM.

Virtuálním DOM a reconciliation

Virtuální DOM v Reactu není implementace skutečného DOM, ale je to datová struktura ve formě JavaScriptových objektů. Do skutečného DOM React promítne pouze změnu mezi novým a předešlým virtuálním DOM. Tento proces se nazývá reconciliation. Manipulace se skutečným DOM pomocí Reactu je výkonově méně náročnější.

Ukázka

Teorii bychom měli, teď se pustíme do reálné ukázky. Uvidíme rozdíl mezi aktualizací DOM přes Web API a pomocí Reactu.

Pro náš příklad bude plně dostačující codepen.io. Kompletní kód si můžete prohlédnout na codepen.io.

Abychom mohli přistupovat k React API a ReactDOM API, do external script v JavaScriptu na Codepen nastavíme knihovny React a ReactDOM.

https://unpkg.com/react@16/umd/react.development.js 
https://unpkg.com/react-dom@16/umd/react-dom.development.js

Vytvoříme dva div elementy. Jeden pro vložení HTML pomocí JavaScriptu a druhý pro React.

<div id=”jsElement”></div>
<div id=”reactElement”></div>

V JavaScriptu načteme elementy do proměnných jsContainer a reactContainer.

const jsContainer = document.getElementById(“jsElement”);
const reactContainer = document.getElementById(“reactElement”);

Pomocí innnerHTML, které je součástí DOM Web API, vložíme div se css třídou counter-border do skutečného DOM.

jsContainer.innerHTML = `
<div class=”counter-border”>
JavaScript
<input />
<h1>${counter}</h1></div>`;

ReactDOM.render zavolá React.createElement, který je následně vložen do divu reactContainer.

ReactDOM.render(
React.createElement(
“div”,
{ className: “counter-border” },
“React “,
React.createElement(“input”),
React.createElement(
“h1”,null,counter)),reactContainer);

React.createElement má tři argumenty:

- První argument je typ HTML tagu a nebo komponenta.

- Druhý argument je objekt. V naší ukázce obsahuje objekt property className: “counter-border”.

- Třetí argument je obsah elementu. Může to být například string a nebo další elementy (komponenty). V našem případě je to nadpis h1 a input.

Nadefinujeme si proměnnou counter, kterou budeme pomocí setInterval každou sekundu navyšovat.

Dále si vytvoříme anonymní funkci update, ve které budeme aktualizovat DOM. Námi vytvořenou funkci update pak voláme pomocí setInterval a každou sekundu tak vyžadujeme aktualizaci DOM.

setInterval(update, 1000);

Zkuste napsat text do prvního inputu. Nejde to. Text zde nezůstane. Uzel je každou sekundu odstraněn z DOM. V případě inputu vytvořeného pomocí Rectu tomu tak není.

V prohlížeči v nástrojích pro vývojáře najděte div s id jsElement a div s id reactElement. Můžete vidět, že React mění pouze nadpis h1. Input zůstává zachován.

Rozdíl mezi aktualizací DOM pomoci Web API a Reactu.

React neodstraní všechny uzly ve virtuálním DOM. Porovná předchozí a novou instanci virtuálního DOM a provede aktualizaci skutečného DOM jen na uzlech, kde došlo ke změně.

Závěrem

Výhody virtuálního DOM a reconciliation („diffing“) algoritmu oceníme hlavně při tvorbě rozsáhlejších uživatelských rozhraní, kde dochází k manipulaci se složitějšími stromovými strukturami. Spolu s deklarativní popisem UI nám React umožňuje více se zaměřit na samotnou tvorbu uživatelského rozhraní a méně se zabývat manipulací s DOM.

--

--