Slovak (Slovenčina) translation by Ryan (you can also view the original English article)

Angular vs. React je jednou z populárnych diskusií medzi front-end vývojármi. Väčšinou je diskusia zaujatá voči jednej technológií. Vyvíjané Googlom a Facebookom (v tomto poradí), Angular a React sú dva populárne technológie, ktoré sú použité k tvorbe jednostránkových aplikácií.
Obsiahle porovnanie medzi Angularom a Reactom je bezprostredné, pretože v niektorých miestach sa významne prekrývajú, napr. tvorba obrazovky aplikácie a iná funkcionalita, ktorá zostáva nedokončená bez pomoci knižnice tretej strany. Prijatie jednej technológie oproti inej je otázkou riešenia problémov a či ho lepšie rieši Angular alebo React. V tomto článku si porovnáme a vytvoríme kontrast medzi siedmimi kľúčovými vlastnosťami medzi Angularom a Reactom.
Som horúci zástanca prístupu code-first (hovorí sa, že kód je viac ako nejaké slová.) Všade, kde to bolo možné som pridal ukážku kódu Angularu a Reactu aby ste mohli stavať na vlastnej intuícii a rozhodnúť sa, čo pre vás je lepšie. Poďme na to!
Framework vs. knižnica
Angular je framework, zatiaľčo React je knižnica.
Čo to vlastne znamená? S Reactom samo o sebe nevytvoríte aplikáciu, pretože jeho úlohou je vykresľovať obrazovky (to je "V" v MVC). React dokáže vytvoriť obrazovky založené na komponentoch, ktorého dáta môžu byť prenesené do podobrazoviek. Ako riešenie tohto problému slúži Flux, čo je architektonický model, ktorý doplňuje React. Architektúra Flux, spolu s Reactom, poskytuje tento scenár:
- Používateľ klikne na prvok v Reacte.
- Spustí sa akcia. Tá akcia je odoslaná do Store pomocou knižnice Dispatcher.
- Store má na starosti stav aplikácie a metódy získania dát. Každá aktualizácia stavu sa odrazí na obrazovkách, čo pomáha obrazovkám uchovať konzistentný stav aplikácie.
Nedáva vám to zmysel? Tento obrázok môže byť nápomocný:

Angular je framework pre tvorbu klientských aplikácií.
AngularJS bol vyvinutý na základe vzoru MVC, čo rozdeľovalo aplikáciu do troch rôznych vrstiev. Kombinácia modelu, obrazovky, ovládača a pridanej komplexity zapríčinilo potrebu pre porozumenie direktív, tovární, služieb a iných komponentov len pre vytvorenie jednostránkovej aplikácie. To je dôvod, prečo Google vývojári prešli na komponentovú architektúru.
Ale keď vaša aplikácia začne rásť, je dôležité mať pevnú štruktúru, ktorá oddelí obchodnú logiku od komponentov. Pretože Angular je framework, núti vás používať štruktúralne rozmiestnenie posunutím obchodnej logiky do modelu (použitím kombinácie modelov a služieb) a "pichať" model do komponentov pomocou Dependency Injection.
Tu je ukážka kódu, ktorá ilustruje ako je obchodná logika uzavretá do modelu a služby User, mimo nášho komponentu.
/* Path: /app/models/User.ts */ export class User { id: number; username: string; password: string; firstName: string; lastName: string; }
/* /app/services/user.service.ts */ import { Injectable } from '@angular/core'; import { Http } from '@angular/http'; import { User } from '../models/User'; @Injectable() export class UserService { constructor(private https: Http) { } getAll() { // API to return all users } create(user: User) { //API call to create user } update(user: User) { //API call to update user } delete(id: number) { //API call to delete user } }
/* Path: /app/page/page.component.ts */ import { Component } from '@angular/core'; import { User } from '../models/User'; import { UserService } from '../services/user.service'; @Component({ templateUrl: 'page.component.html' }) export class PageComponent { currentUser: User; users: User[] = []; constructor(private userService: UserService) { //Dependency is Injected inside the constructor's arguments deleteUser(id: number) { this.userService.delete(id).subscribe(() => { #Do Something}); } private loadAllUsers() { this.userService.getAll().subscribe(users => { #Do something else }); } }
<!---Path: /app/home/page.component.html --> <div class="title"> <h2>All users:</h2> <ul> <li *ngFor="let user of users"> {{user.username}} ({{user.firstName}} {{user.lastName}}) - <a (click)="deleteUser(user.id)">Delete</a> </li> </ul> </div>
Prístup založený na komponentoch
Komponenty sú v Angular aplikácii najzákladnejším blokom tvorby UI. Aplikácia je strom komponentov.
Čo sú komponenty? V Angulari komponenty sú triedy napísané v TypeScripte, ktoré sú označené tapetárom @Component
. Vo vnútri týchto tapetárov môžeme popísať, ktorú šablónu, štýly, selektor, atď. bude komponent obsahovať.
Hierarchia komponentu je navrhnutá tak, že môžete pričleniť štruktúru a funkcionalitu pod jeden objekt. Tu je architektonický prehľad komponentov a ako sa v Angulari spájajú so všetkým ostatným.

Zdieľanie dát medzi komponentmi je možný vďaka hniezdeniu komponentov:
/* UserParentComponent.ts */ import { Component } from '@angular/core'; // The <user-child> selector is nested inside <user-parent>. Each user is passed down as a property. @Component({ selector: 'user-parent', template: ` <h2>There are {{users.length}} registered users {{status}} now</h2> <user-child *ngFor="let user of users" [user]="user" [status]="status"> </user-child> ` }) export class UserParentComponent { users: { id: number, name: string }[] = [ { "id": 0, "name": "Chris" }, { "id": 1, "name": "Dwayne" }, { "id": 2, "name": "Eve" } ]; status: string = "online"; }
/* UserChildComponent.ts */ import { Component, Input } from '@angular/core'; // Input properties are adorned with @decorators // user & status are input properties @Component({ selector: 'user-child', template: ` <h2>{{user.name}}</h3> <p> id : {{user.id}} </p> <p> Status: {{status}} </p> ` }) export class UserChildComponent { @Input() user: { id: number, name: string }; @Input() status: string; }
Koncept komponentov je hlboko usadený ako v Angulari, tak aj v Reacte. Facebook nazýva React knižnicou založenou na komponentoch, ktorá vám umožní vytvárať interaktívne rozhrania. Narozdiel od Angularu, React komponenty sú čisté JavaScript funkcie so svojvoľným počtom vstupov a výstupov. Kód nižšie je komponent definovaný pomocou JavaScript funkcie a triedy v ES6.
// Writing components using JavaScript functions function Welcome(props) { return <h1>Hello, {props.name}</h1>; } // Writing components using ES6 Class class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } }
Počas tvorby komponentov sa budeme držať štandardov ES6, pretože to Facebook odporúča. Každý komponent prijíma svojvoľný počet vstupov, ktoré sú uložené v objekte nazvanom props
.
Taktiež má metódu render
, ktorá, ako jej názov napovedá, pri jej spustení vykresľuje prvky. Každý komponent si udržiava svoj vlastný stav (pomocou this.state
) a vždy, keď sa stav zmení, funkcia render sa znova spustí.
Vlastnosti jazykov: TypeScript vs. ES6
Angular aplikácie sú napísané v TypeScripte, čo je nadradený voči ECMA2015 a používa transpiler, aby mohol byť výrazné typovaný .ts súbor skompilovaný do .js súbora. TypeScript ponúka jazykové rozšírenia, ktoré sú navrhnuté aby mohla byť práca s JavaScriptom jednoduchšia a spája informácie o typoch s JavaScriptovými entitami k presadeniu kontroly typov a rozšíreniu vývoja.
Niektoré z kľúčových vlastností TypeScriptu sú voliteľné statické typovanie a podpora pre rozhrania, triedy a tapetáre. (Tapetáre sú funkcie, ktoré začínajú na "@" a za ňu nasleduje trieda, parameter alebo vlasnosť.)
Môžeme pokračovať v Reacte? Jedna z dôležitých jazykových funkcií Reactu je viditeľná na tejto ukážke.
function Tweet(props) { return( <div className="tweet"> <img src="http://twitter.com/some-avatar.png" className="tweet__avatar" /> <div className="tweet__body"> <p>This is a tweet.</p> </div> </div> ); }
Nie je to skvelé? Pomocou JSX môžete dať XML/HTML značky do vášho JavaScript súbora, čo pridáva rozšírené schopnosti do JavaScriptu. Musíme ale použiť kompilátor ako je Babel, ktorý kompiluje náš JSX kód do kódu, ktorý prehliadače rozumejú. Kód vyššie bude skompilovaný do tohto kódu:
"use strict"; function Tweet(props) { return React.createElement( "div", { className: "tweet" }, React.createElement("img", { src: "http://twitter.com/some-avatar.png", className: "tweet__avatar" }), React.createElement( "div", { className: "tweet__body" }, React.createElement( "p", null, "This is a tweet." ) ) ); }
Síce sa odporúča použitie JSX, ak ste proti myšlienke použitia HTML značiek v JavaScripte, môžete používať funkciu React.createElement()
.
Okrem toho môžete používať buď štandardy ES6 alebo tradičnú formu JavaScriptu. Hoci je ES6 nový, pridáva dosť nových vlastností ako sú triedy, šípkové funkcie, šablonóvé literály, deštrukturovanie, let a const. Jedinou nevýhodou je, že pridáva trošku viac kódu, pretože vždy, keď vytvoríme constructor()
potrebujeme zavolať super()
a this
nie je v metódach automaticky zadefinovaná do triedy.
class User extends React.Component { constructor(props) { //bloat code alert super(props); this.handleSubmit = this.handleSubmit.bind(this); this.handleInputChange = this.handleInputChange.bind(this); } handleSubmit(user) { //Method to handle submit } handleInputChange(user) { //Method to handle input } render() { return ( <div> <UserRegistration onSubmitSuccess={this.handleSubmit} onInputChange={this.handleInputChange} /> </div> ); } }
Kontrola typov v Angular vs. PropTypes v Reacte
Statická kontrola typov je vykonaná v čase kompilácie. Kompilátor vás upozorní na potencionálne nesúlady typov a zistí isté chyby, ktoré by mohli ostať nepovšimnuté. Taktiež pridanie typu do premennej, vlastnosti alebo parametra funkcie môže urobiť kód čitateľnejším a udržateľnejším.
Premenné a deklarácie funkcií sú expresívnejšie vďaka deklarácii dátových typov. Viac o rôznych primitívnych dátových typoch nájdete v dokumentácii TypeScriptu.
let isLoggedIn: boolean = false; let id: number = 10; let name: string = "Davis"; let list: number[] = [1, 2, 3]; enum Color {Red, Green, Blue}; let c: Color = Color.Red; let bucket: any = 4; bucket = "I can be a string"; bucket = false; // or a boolean
Definícia podpisu pre API pomocou rozhrania robí kód menej nezmyselným a dá sa mu lepšie porozumieť. Rozhranie slúži ako rýchla príručka, ktorá pomáha začať pracovať s kódom a šetrí čas strávený čítaním dokumentácie alebo skutočnej implementácie knižnice.
interface ButtonSettings { text: string; size?: { width: number; height: number; }; color?: string; } function createButton(settings: ButtonSettings) { ... } createButton({ text: 'Submit' }); // OK createButton({ text: 'Submit', size: { width: 70, height: 30 }}); // OK createButton({ text: 'Submit', color: 43); // Not OK: 43 isn't a string createButton({ text: 'Submit', size: { width: 70 }); // Not OK: size needs a height as well createButton({ color: 'Blue'}); // Not OK: 'text' member is required
Kľúčové slovo type
môže byť v TypeScripte použité pre vytvorenie prezývky typu. Môžete vytvárať nové spojené alebo skrížené primitívne typy.
//Union Types type Age = number | string; function getAge (age: Age): string { return `You are ${age}!`; } let ofSusan: Age =21; let ofTyler: Age = 'thirty one'; getAge(ofSusan); // You are 21! getAge(ofTyler); // You are thirty one! //Intersection Types interface Name{ name(firstName: string, lastName: string): string; } interface Age { age(current: number): number; } // assign intersection definition to alias User type User = Name & Age; function createUser (testUser: User) { testUser.name("David","John"); testUser.age(99); testUser.address(); //error
React má obmedzenú podporu pre kontrolu typov, pretože ES6 ich samo o sebe nepodporuje. Avšak môžete implementovať kontrolu typov pomocou knižnice prop-types
vyvýjanú tímom Reactu. Kontrola, či kľúč v objekte props
je reťazec môže byť vykonaná pomocou kódu nižšie.
import PropTypes from 'prop-types'; //importing prop-types library class Greeting extends React.Component { render() { return ( <h1>Hello, {this.props.name}</h1> <P> My age is, {this.props.age} </h2> ); } } Greeting.propTypes = { name: PropTypes.string; age: PropTypes.number; };
Ale prop-types
nie je obmedzený na reťazce, čísla alebo boolean. Môžete s tým robiť omnoho viac, ako je popísané v dokumentácii knižnice. Avšak keď naozaj chcete používať statickú kontrolu typov, mali by ste použiť niečo ako Flow, čo je knižnica pre statickú kontrolu typov pre JavaScript.
Rýchla tvorba: Angular CLI vs. create-react-app
Začatie projektu môže byť spočiatku zábava, avšak proces nastavovania štruktúry priečinka, písania kódu pre komponenty a spustenia aplikácie je zbytočný a neproduktívny. Najlepšou stratégiou je začať čo najrýchlejšie a zamerať sa na skutočný vývoj aplikácie. Vďaka Googlu a Facebooku máte dostupné nástroje pre jednoduchú tvorbu aplikácií.
Nastavenie Angularu CLI pre Angular a create-react-app pre React je jednoduché pomocou npm.
// Angular CLI $ npm install -g @angular/cli // create-react-app $ npm install -g create-react-app
Pre vytvorenie novej Angular aplikácie použite nasledujúci príkaz:
$ ng new PROJECT-NAME $ ng serve
Ale to nie je všetko. Príkaz ng generate
vám dovoľuje vytvárať komponenty, trasy, pipes, direktíva a služby.
$ ng generate component Page installing component create src\app\page\page.component.css create src\app\page\page.component.html create src\app\page\page.component.spec.ts create src\app\page\page.component.ts update src\app\app.module.ts
Angular CLI dokáže omnoho viac, ako je vytvorenie balíčka vašej aplikácie, spustenie testov a end-to-end testing. Viac o tom nájdete na GitHube.
Na druhej strange, create-react-app
je oficiálne podporovaný spôsob, ako vytvoriť aplikáciu v Reacte bez konfigurácie.
$ npm install -g create-react-app
Toto vytvorí plne funkčnú React aplikáciu spolu so prednastavenými závislosťami Babel a webpack. Aplikáciu môžete spustiť pomocou npm start
.
Dostupné skripty môžete nájsť v súbore package.json.
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } }
Väzba dát: Dvojsmerná vs. jednosmerná
Väzba dát je vlastnosť, ktorá povoľuje synchronizáciu dát medzi stavom aplikácie (model) a obrazovkou. V jednosmernom programe každá zmena automaticky zaktualizuje obrazovku. Na druhej strane, dvojsmerná väzba spája vlastnosti a udalosti pod jeden objekt, napr. každá modifikácia zaktualizuje obrazovku a opačne.
V Reacte sú vlastností prenesené z hlavného do podkomponentu, čo je známe ako aj jednosmerný prietok dát. Stav komponentu je zavretý a nie je dostupný iným komponentom, pokiaľ to nie je prenesené ako vlastnosť, napr. stav komponentu sa stane vlastnosťou podkomponentu.
class UserChild extends React.Component { render() { let userData = this.props.users.map( (user) => { return (<p> <strong>{user.id} </strong> : {user.name} </p>); }); return ( <div> <h2> Hello. The server is {this.props.status} </h2> {userData} </div> ); } } class UserParent extends React.Component { constructor() { super(); //State gets defined here this.state = { status: "Online" } } render() { return ( <div> <UserChild users={this.props.users} status={this.state.status} /> </div> ); } } var USERS = [ { "id": 0, "name": "Chris" }, { "id": 1, "name": "Dwayne" }, { "id": 2, "name": "Eve" } ]; ReactDOM.render( <UserParent users={USERS} />, document.getElementById('container') );
Ale čo keď chceme preniesť dáta naspäť hore? Dá sa to cez udalosti a spätné volania. Dokumentácia Reactu má dobrý príklad na tento prípad.
Techniky väzby dát dostupné v Angulari sú jednou z niekoľkých vlastností, ktoré robia Angular zaujímavým. Angular má prednastavenú podporu pre interpoláciu, jednosmernú väzbu, dvojsmernú väzbu a väzbu udalostí.
Pomocou interpolácie viete jednoducho prepojiť vlastnosti komponentu do vnútra značky alebo atribútov.
<p>Vitajte naspäť, {{currentUser.name}}!</p>
Väzba vlastností je podobná interpolácii v tom zmysle, že môžete prepojiť vlastnosti prvkov do vlastností komponentu. Väzba vlastností povoľuje komunikáciu medzi komponentmi a sú odovzdávané rovnako ako v Reacte.
<img [src]="userImgUrl">
<user-child [user]="currentUser"></user-child>
Väzby udalostí prietok dát v opačnom smere, napr. z prvku do komponentu. V tomto prípade je cieľovou udalosťou click
a keď udalosť sa uskutoční, spustí sa metóda onSave()
.
<button (click)="onSave()">Save</button>
Ale najdôležitejšou vlastnosťou je dvojstranná väzba pomocou [(ngModel)]
. Toto spája väzbu vlastnosti a udalosti do jednej direktívy a je užitočný vo formulároch a textových poliach.
<div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name"> </div>
Vykresľovanie na serveri
Vykresľovanie na serveri je tradičná technika vykresľovania. V tomto prípade nám server vráti celý HTML súbor a prehliadač má za úlohu ten súbor zobraziť používateľovi. Na druhej strane, vykresľovanie na klientovi vráti základy HTML dokumentu, štýlový súbor a JavaScript súbor.
Ten JavaScript vytvorí ďalšie požiadavky pre vykreslenie zvyšku stránky. React, Angular a iné moderné front-endové knižnice sú skvelým príkladom vykresľovania na klientovi. Je to očividné, hlavne keď sa pozriete na zdroj vašej aplikácie.
Ale vykresľovanie na klientovi má nevýhodu v tom, že to nie je skvelé pre SEO a vracia nedokončený HTML obsah, čo nie je dobré keď budete zdieľať váš odkaz na sociálne siete. Angular má riešenie s názvom Angular Universal, čo sa stará o to, aby bola vaša aplikácia priateľská pre vyhľadávače. Je to knižnica vytvorená tímom Angularu a je veľmi obľúbená.
Universal využíva techniky predkreslenia, kde celá stránka je najprv vykreslená v serveri a potom o pár sekúnd je vykreslená u klienta. Pretože sa to všetko deje pod kapotou, požívateľ si ničoho nevšimne.
Ak používate React a Redux, dokumentácia Reduxu má skvelý návod na nastavenie vykresľovania na serveri. Taktiež môžete nastaviť React aby bol vykreslený na serveri pomocou komponentov BrowserRouter
a StaticRouter
dostupné v knižnici react-router
. Viac o tom si môžete prečítať v článku na Medium. Ale keď je vašou prioritou výkon a optimizácia, skúste next.js, čo je knižnica pre vykresľovanie na serveri pre React.
Záver
Porovnávanie celého frameworku a robustnej knižnice pre UI nie je férové. Sú to ale pokročilé JavaScript technológie, ktoré sa používajú pre tvorbu jednostránkových aplikácií a tento článok by mal byť nápomocný pri výbere.
Čo si myslíte o Angular vs. React? Napíšte nám do komentárov.
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post