Plusy i minusy reakcji Facebooka na komponenty sieciowe (polimery)

521

Jakie są główne zalety Facebook React w stosunku do nadchodzącej specyfikacji Web Components i vice versa (a może bardziej porównywalne porównanie jabłek z jabłkami byłoby z biblioteką Polymer Google )?

Zgodnie z rozmową JSConf EU i stroną główną React, główne zalety React to:

  • Odsprzęganie i zwiększona spójność za pomocą modelu komponentowego
  • Abstrakcja, kompozycja i ekspresja
  • Wirtualne DOM i zdarzenia syntetyczne (co w zasadzie oznacza, że ​​całkowicie ponownie wdrożyły DOM i jego system zdarzeń)
    • Umożliwia obsługę nowoczesnych zdarzeń HTML5 w IE 8
    • Renderowanie po stronie serwera
    • Testowalność
    • Powiązania z SVG, VML i <canvas>

Prawie wszystko, co wspomniano, jest wbudowane w przeglądarki natywnie za pośrednictwem składników sieci Web, z wyjątkiem tej wirtualnej koncepcji DOM (oczywiście). Widzę, w jaki sposób wirtualny DOM i wydarzenia syntetyczne mogą być dziś przydatne do obsługi starych przeglądarek, ale czy nie wyrzucam ogromnej części natywnego kodu przeglądarki, jak strzelanie sobie w stopę w perspektywie długoterminowej? Jeśli chodzi o współczesne przeglądarki, czyż nie jest to dużo niepotrzebnego narzutu / ponownego wynalezienia koła?

Oto niektóre rzeczy, których według mnie brakuje React , za które zadbają o Ciebie składniki sieciowe. Popraw mnie, jeśli się mylę.

  • Natywna obsługa przeglądarki (czytaj „z pewnością szybsze”)
  • Napisz skrypt w języku skryptowym, napisz style w języku stylistycznym, napisz znaczniki w języku znaczników.
  • Styl enkapsulacji za pomocą Shadow DOM
    • Zamiast tego React ma to , co wymaga pisania CSS w JavaScript. Nie ładna
  • Wiązanie dwustronne
CletusW
źródło
12
Wrt. wiązanie dwukierunkowe. Ta funkcja jest problematyczna w skali. W trywialnych przypadkach działa dobrze, ale w rzeczywistych przypadkach zwykle okazuje się, że aby utrzymać zarządzanie kodem, potrzebujesz viewmodel, aby powiązać, zamiast wiązania z rzeczywistym modelem, co sprawia, że ​​wiązanie dwustronne jest znacznie mniej przydatne niż początkowo wydawało się. Myślę, że zaletą React może być to, że nie zapewnia dwukierunkowego wiązania, ponieważ wymusza odpowiednią architekturę przepływu danych.
Joeri Sebrechts,
8
Patrzyłem na React, Angular i Knockout. Uważam Knockout za „najczystszy” pod względem rozdzielania szablonów interfejsu użytkownika, danych i wiązania. Chciałem zareagować, ale próbując stworzyć prosty Combobox, zdałem sobie sprawę, że pisałem znacznie więcej kodu i mieszałem logikę renderowania z szablonami html .. znacznie bardziej niż przy użyciu czegoś takiego jak html / jina2. Wydaje mi się, że te biblioteki / apis przenoszą nas do tyłu, a nie do przodu. Najlepszą rzeczą w React jest manipulacja wirtualnym domem, ale widzę, że przychodzi do innych ustalonych frameworków wcześniej niż później.
mike01010
41
Jestem bardzo zaskoczony (i również zadowolony!), Że to pytanie nie zostało zamknięte jako „głównie oparte na opiniach”.
iconoclast
4
Nie jest możliwe napisanie „skryptu w języku skryptowym” i „znaczników w języku znaczników”, jeśli wykonujesz jakiekolwiek szablony. Kątowe, polimerowe itp. Używają szablonu DSL osadzonego w HTML. React używa szablonu DSL osadzonego w JS (JSX). Problem z osadzaniem DSL w HTML polega na tym, jak ustalić zakres pobierania wartości z JS. Prowadzi to do złożonego systemu Angular $ scope. Z drugiej strony w JSX zakres zmiennych w szablonach to po prostu zakres JS - uważam, że jest to mniej skomplikowane.
Andy
3
W tej chwili komponenty React (chyba że źle napisane) byłyby szybsze niż to samo w dowolnym frameworku związanym z DOM. V-dom i różna magia to USP reakcji. Chodzi mi o to - dlaczego przeglądający nie mieliby budować czegoś takiego w swoim rodzimym zestawie funkcji. Co ich powstrzymuje, a jeśli nic (ich nie powstrzyma), to prawdopodobnie React prawdopodobnie będzie krótkotrwały.
fasttrainofoughts

Odpowiedzi:

664

Aktualizacja:  ta odpowiedź wydaje się dość popularna, więc poświęciłem trochę czasu na jej oczyszczenie, dodanie nowych informacji i wyjaśnienie kilku rzeczy, które moim zdaniem nie były wystarczająco jasne. Proszę o komentarz, jeśli uważasz, że coś jeszcze wymaga wyjaśnienia lub aktualizacji.

Większość twoich obaw jest tak naprawdę kwestią opinii i osobistych preferencji, ale postaram się odpowiedzieć tak obiektywnie, jak to możliwe:

Natywny a skompilowany

Napisz JavaScript w waniliowym JavaScript, napisz CSS w CSS, napisz HTML w HTML.

W tamtych czasach trwały gorące debaty, czy należy  ręcznie napisać natywny asembler, czy użyć języka wyższego poziomu, takiego jak C, aby kompilator wygenerował dla ciebie kod asemblera. Jeszcze wcześniej ludzie nie ufali asemblerom i woleli pisać natywny kod maszynowy ręcznie ( i nie żartuję ).

Tymczasem dziś wiele osób pisze HTML w Haml lub Jade , CSS w Sass lub Less i JavaScript w CoffeeScript lub TypeScript . Jest tutaj. To działa. Niektórzy wolą, inni nie.

Chodzi o to, że nie ma nic zasadniczo złego w nie pisaniu JavaScript w waniliowym JavaScript, CSS w CSS i HTML w HTML. To naprawdę kwestia preferencji.

Wewnętrzne a zewnętrzne DSL

 Zamiast tego istnieje styl enkapsulacji za pomocą Shadow DOM React, który wymaga pisania CSS w JavaScript. Nie ładna

Ładne czy nie, z pewnością jest wyraziste. JavaScript jest bardzo potężnym językiem, znacznie potężniejszym niż CSS (nawet włączając w to którykolwiek z preprocesorów CSS). To zależy od tego, czy wolisz wewnętrzne czy zewnętrzne DSL dla tego rodzaju rzeczy. Znowu kwestia preferencji.

(Uwaga: mówiłem o stylach wbudowanych w programie React, do których odwołano się w pierwotnym pytaniu).

Rodzaje DSL - wyjaśnienie

Aktualizacja: Czytając moją odpowiedź jakiś czas po jej napisaniu, myślę, że muszę wyjaśnić, co mam na myśli. DSL jest językiem specyficznym dla domeny i może być wewnętrzny (przy użyciu składni języka hosta, takiego jak JavaScript - jak na przykład React bez JSX, lub jak style wbudowane w React wspomniane powyżej) lub może być zewnętrzny (przy użyciu innej składni niż język hosta - tak jak w tym przykładzie byłoby wstawianie CSS (zewnętrznego DSL) wewnątrz JavaScript).

Może to być mylące, ponieważ niektóre literatury używają terminów innych niż „wewnętrzny” i „zewnętrzny” do opisania tego rodzaju DSL. Czasami zamiast „wewnętrznego” używa się słowa „osadzony”, ale słowo „osadzony” może oznaczać różne rzeczy - na przykład Lua jest opisana jako „Lua: rozszerzalny język osadzony”, w którym osadzony nie ma nic wspólnego z wbudowanym (wewnętrznym) DSL (w w którym sensie jest wręcz przeciwnie - zewnętrzna DSL), ale oznacza to, że jest osadzony w tym samym sensie, co, powiedzmy, SQLite jest osadzoną bazą danych. Istnieje nawet eLua, w którym „e” oznacza „osadzony” w trzecim znaczeniu - że jest przeznaczony dla systemów wbudowanych! Dlatego nie lubię używać terminu „wbudowany DSL”, ponieważ takie rzeczy jak eLua mogą być „DSL”, które są „osadzone” na dwa różne sposoby, ale wcale nie są „osadzonymi DSL”!

Co gorsza, niektóre projekty wprowadzają jeszcze więcej zamieszania w miksie. Na przykład. Szablony Flatiron są opisane jako „bez DSL”, podczas gdy w rzeczywistości jest to idealny przykład wewnętrznej DSL o składni takiej jak:map.where('href').is('/').insert('newurl');

To powiedziawszy, kiedy napisałem: „JavaScript jest bardzo potężnym językiem, znacznie potężniejszym niż CSS (nawet włączając którykolwiek z preprocesorów CSS). Zależy to od tego, czy wolisz wewnętrzne czy zewnętrzne DSL dla tego rodzaju rzeczy. Ponownie, kwestia preferencji ”. Mówiłem o tych dwóch scenariuszach:

Jeden:

/** @jsx React.DOM */
var colored = {
  color: myColor
};
React.renderComponent(<div style={colored}>Hello World!</div>, mountNode);

Dwa:

// SASS:
.colored {
  color: $my-color;
}
// HTML:
<div class="colored">Hello World!</div>

W pierwszym przykładzie użyto tego, co opisano w pytaniu jako: „pisanie CSS w JavaScript. Niezbyt ładne”. Drugi przykład wykorzystuje Sass. Chociaż zgadzam się, że używanie JavaScript do pisania CSS może nie być ładne (w przypadku niektórych definicji „ładnych”), ale ma jedną zaletę.

Mogę mieć zmienne i funkcje w Sass, ale czy mają one zakres leksykalny czy dynamiczny? Czy są wpisywane statycznie czy dynamicznie? Mocno czy słabo? Co z typami liczbowymi? Typ kooperacji? Które wartości są prawdziwe, a które fałszywe? Czy mogę mieć funkcje wyższego rzędu? Rekurencja? Woła ogon? Zamknięcia leksykalne? Czy są oceniane w normalnej kolejności lub kolejności stosowania? Czy jest leniwa lub chętna ocena? Czy argumenty funkcji są przekazywane przez wartość czy przez odwołanie? Czy są zmienne? Niezmienny? Uporczywy? Co z przedmiotami? Klasy? Prototypy? Dziedzictwo?

To nie są trywialne pytania, a jednak muszę znać odpowiedzi, jeśli chcę zrozumieć kod Sass or Less. Znam już odpowiedzi na JavaScript, co oznacza, że ​​już rozumiem każdą wewnętrzną DSL (jak style wbudowane w React) na tych samych poziomach, więc jeśli używam React, muszę znać tylko jeden zestaw odpowiedzi na te (i wiele podobnych ) pytania, podczas gdy używam np. Sass i Kierownica muszę więc znać trzy zestawy tych odpowiedzi i zrozumieć ich konsekwencje.

Nie oznacza to, że w ten czy inny sposób jest zawsze lepszy, ale za każdym razem, gdy wprowadzasz inny język do miksu, płacisz pewną cenę, która może nie być tak oczywista na pierwszy rzut oka, a ta cena jest złożona.

Mam nadzieję, że wyjaśniłem trochę, co pierwotnie miałem na myśli.

Powiązanie danych

Wiązanie dwustronne

To naprawdę interesujący temat, a właściwie kwestia preferencji. Dwukierunkowa nie zawsze jest lepsza niż jednokierunkowa. To pytanie, jak chcesz modelować stan zmiennych w swojej aplikacji. Zawsze postrzegałem dwustronne powiązania jako pomysł nieco sprzeczny z zasadami programowania funkcjonalnego, ale programowanie funkcjonalne nie jest jedynym paradygmatem, który działa, niektórzy wolą takie zachowanie i oba podejścia wydają się działać całkiem dobrze w praktyce. Jeśli interesują Cię szczegóły decyzji projektowych związanych z modelowaniem stanu w React, obejrzyj przemówienie Pete Hunta (powiązane z pytaniem) oraz przemówienie Toma Occhino i Jordana Walke'a,  którzy bardzo dobrze to wyjaśniają w moja opinia.

Aktualizacja: Zobacz także inne przemówienie Pete Hunta: Bądź przewidywalny, niepoprawny: funkcjonalne programowanie DOM .

Aktualizacja 2: Warto zauważyć, że wielu programistów sprzeciwia się dwukierunkowemu przepływowi danych lub dwukierunkowemu wiązaniu, niektórzy nawet nazywają to anty-wzorcem. Weźmy na przykład Flux architekturę aplikacji, który wyraźnie unika MVC model (który okazał się być trudne do skalowania dla dużych Facebook i Instagram aplikacji) na rzecz ściśle jednokierunkowy przepływ danych (patrz Way Hacker: Rethinking Web Development App Facebook rozmawiać przez Tom Occhino, Jing Chen i Pete Hunt za dobre wprowadzenie). Również wiele krytyki przeciwko AngularJS (najpopularniejszy framework sieciowy, który jest luźno oparty na modelu MVC, znany z dwukierunkowego wiązania danych) zawiera argumenty przeciwko temu dwukierunkowemu przepływowi danych, patrz:

Aktualizacja 3: Kolejnym interesującym artykułem, który ładnie wyjaśnia niektóre z omawianych powyżej problemów, jest Dekonstruowanie strumienia ReactJS - nieużywanie MVC z ReactJS przez Mikaela Brassmana, autora RefluxJS (prosta biblioteka dla architektury aplikacji do jednokierunkowego przepływu danych zainspirowana przez Flux).

Aktualizacja 4: Ember.js obecnie odchodzi od dwukierunkowego wiązania danych, aw przyszłych wersjach domyślnie będzie jednokierunkowy. Zobacz: Przyszłość Embera przemówienie Stefana Pennera z Embergarten Symposium w Toronto 15 listopada 2014 r.

Aktualizacja 5: Zobacz także: Droga do Ember 2.0 RFC - ciekawa dyskusja w żądaniu ściągnięcia Toma Dale'a :

„Kiedy zaprojektowaliśmy oryginalną warstwę szablonów, doszliśmy do wniosku, że wykonanie dwukierunkowego powiązania wszystkich danych nie było zbyt szkodliwe: jeśli nie ustawisz powiązania dwukierunkowego, jest to de facto wiązanie jednokierunkowe!

Od tego czasu zdaliśmy sobie sprawę (z pewną pomocą naszych przyjaciół z React), że komponenty chcą móc przekazywać dane swoim dzieciom bez konieczności pilnowania nieprzyzwoitych mutacji.

Ponadto komunikacja między komponentami jest najczęściej najbardziej naturalnie wyrażana jako zdarzenia lub wywołania zwrotne . Jest to możliwe w Ember, ale dominacja dwukierunkowych powiązań danych często prowadzi ludzi na ścieżkę korzystania z dwustronnych powiązań jako kanału komunikacji . Doświadczeni programiści Ember (zwykle) nie popełniają tego błędu, ale łatwo go popełnić. ” [Podkreślenie dodane]

Natywny vs. VM

Natywna obsługa przeglądarki (czytaj „z pewnością szybsze”)

Teraz wreszcie coś, co nie jest kwestią opinii.

W rzeczywistości jest dokładnie na odwrót. Oczywiście „rodzimy” kod może być napisany w C ++, ale jak myślisz, w czym są napisane silniki JavaScript?

W rzeczywistości silniki JavaScript są naprawdę niesamowite w optymalizacjach, których używają dzisiaj - i nie tylko V8, ale także SpiderMonkey, a nawet Chakra. I pamiętaj, że w kompilatorach JIT kod jest nie tylko tak natywny, jak to tylko możliwe, ale istnieją również możliwości optymalizacji czasu wykonywania, których nie da się zrobić w żadnym statycznie skompilowanym kodzie.

Kiedy ludzie myślą, że JavaScript działa wolno, zwykle mają na myśli JavaScript, który uzyskuje dostęp do DOM. DOM jest wolny. Jest natywny, napisany w C ++, a jednak jest powolny jak diabli ze względu na złożoność, którą musi wdrożyć.

Otwórz konsolę i napisz:

console.dir(document.createElement('div'));

i zobacz, ile właściwości divmusi zaimplementować pusty element, który nawet nie jest dołączony do DOM. Są to tylko  właściwości pierwszego poziomu , które są „właściwościami własnymi”, tj. nie odziedziczony z łańcucha prototypów:

wyrównaj, oczekuj, zmień, ontimeupdate, onsuspend, onsubmit, onstalled, onshow, onselect, onseeking, onseeked, onscroll, onresize, onreset, onratechange, onprogress, onplaying, onplay, onpause, onmouse onmouse onmouse onmouse onmouse onmouseenter, onmousedown, onloadstart, onloadedmetadata, onloadeddata, onload, onkeyup, onkeypress, onkeydown, oninvalid, oninput, onfocus, onerror, onended, onemptied, ondurationchange, ondrop, ondragstart, ondragag, ondrdrd oncontextmenu, onclose, onclick, onchange, oncanplaythrough, oncanplay, oncancel, onblur, onabort, spellcheck, isContentEditable, contentEditable, outerText, innerText, accessKey, ukryty, webkitdropzone, przeciągalny, tabIndex, reż, tytuł, tłumaczeniefirstElementChild, dzieci, nextElementSibling, previousElementSibling, onwheel, onwebkitfullscreenerror, onwebkitfullscreenchange, onselectstart, onsearch, onpaste, oncut, oncopy, onbeforepaste, onbeforecut, onbeforecopy, webWitTextHewLMLText, klasa clientHeight, clientWidth, clientTop, clientLeft, offsetParent, offsetHeight, offsetWidth, offsetTop, offsetLeft, localName, prefiks, przestrzeń nazwURI, id, styl, atrybuty, tagName, parentElement, textContent, baseURI, ownerDocument, nextSibling, previousSibling, lastHild child, firstCild parentNode, nodeType, nodeValue, nodeNameonline przestrzeń nazwURI, id, styl, atrybuty, tagName, parentElement, textContent, baseURI, ownerDocument, nextSibling, previousSibling, lastChild, firstChild, childNodes, parentNode, nodeType, nodeValue, nodeNameonline przestrzeń nazwURI, id, styl, atrybuty, tagName, parentElement, textContent, baseURI, ownerDocument, nextSibling, previousSibling, lastChild, firstChild, childNodes, parentNode, nodeType, nodeValue, nodeNameparentElement, textContent, baseURI, ownerDocument, nextSibling, previousSibling, lastChild, firstChild, childNodes, parentNode, nodeType, nodeValue, nodeNameparentElement, textContent, baseURI, ownerDocument, nextSibling, previousSibling, lastChild, firstChild, childNodes, parentNode, nodeType, nodeValue, nodeName

Wiele z nich to tak naprawdę obiekty zagnieżdżone - aby zobaczyć właściwości drugiego poziomu (własne) pustego obiektu macierzystego divw przeglądarce, zobacz to skrzypce .

Mówię poważnie, właściwość onvolumechange na każdym węźle div? Czy to pomyłka? Nie, to tylko starsza wersja tradycyjnego modelu zdarzeń DOM Level 0 jednej z procedur obsługi zdarzeń „, która musi być obsługiwana przez wszystkie elementy HTML , ponieważ zarówno atrybuty treści, jak i atrybuty IDL” [podkreślenie dodane] w sekcji 6.1.6.2 specyfikacji HTML autor: W3C - nie da się tego obejść.

Tymczasem są to właściwości pierwszego poziomu fałszywej DOM divw React:

rekwizyty, _owner, _lifeCycleState, _pendingProps, _pendingCallbacks, _pendingOwner

Całkiem różnica, prawda? W rzeczywistości jest to cały obiekt zserializowany do JSON ( LIVE DEMO ), ponieważ hej, tak naprawdę możesz  serializować go do JSON, ponieważ nie zawiera żadnych okrągłych odniesień - coś nie do pomyślenia w świecie natywnego DOM ( gdzie po prostu rzuciłby wyjątek ):

{
  "props": {},
  "_owner": null,
  "_lifeCycleState": "UNMOUNTED",
  "_pendingProps": null,
  "_pendingCallbacks": null,
  "_pendingOwner": null
}

Jest to właściwie główny powód, dla którego React może być szybszy niż natywny DOM przeglądarki - ponieważ nie musi implementować tego bałaganu .

Zobacz prezentację Stevena Luschera, aby zobaczyć, co jest szybsze: natywny DOM napisany w C ++ lub fałszywy DOM napisany całkowicie w JavaScript. To bardzo uczciwa i zabawna prezentacja.

Aktualizacja: Ember.js w przyszłych wersjach będzie korzystał z wirtualnego DOM silnie zainspirowanego Reactem w celu poprawy wydajności. Zobacz: Przyszłość Embera przemówienie Stefana Pennera z Embergarten Symposium w Toronto 15 listopada 2014 r.

Podsumowując: funkcje komponentów sieci Web, takie jak szablony, powiązanie danych lub elementy niestandardowe, będą miały wiele zalet w stosunku do React, ale dopóki sam model obiektu dokumentu nie zostanie znacznie uproszczony, wydajność nie będzie jednym z nich.

Aktualizacja

Dwa miesiące po opublikowaniu tych odpowiedzi pojawiło się kilka istotnych informacji. Jak właśnie napisałem na Twitterze , najnowsza wersja edytora tekstowego Atom napisana przez GitHub w JavaScript korzysta z React Facebooka, aby uzyskać lepszą wydajność, mimo że według Wikipedii „Atom jest oparty na Chromium i napisany w C ++”, więc ma pełną kontrolę nad natywna implementacja DOM C ++ (patrz The Nucleus of Atom ) i gwarantuje obsługę komponentów Web, ponieważ jest dostarczana z własną przeglądarką internetową. To tylko najnowszy przykład projektu z prawdziwego świata, w którym można było zastosować jakąkolwiek inną optymalizację, zwykle niedostępną dla aplikacji internetowych, a jednak zdecydowano się użyć React, który sam jest napisany w JavaScript, aby osiągnąć najlepszą wydajność, mimo że Atom nie został zbudowany z Reactem, więc zrobienie tego nie było trywialną zmianą.

Aktualizacja 2

Istnieje interesujące porównanie autorstwa Todda Parkera za pomocą WebPagetest do porównania wydajności przykładów TodoMVC napisanych w Angular, Backbone, Ember, Polymer, CanJS, YUI, Knockout, React i Shoestring. To najbardziej obiektywne porównanie, jakie do tej pory widziałem. Istotne jest tutaj to, że wszystkie odpowiednie przykłady zostały napisane przez ekspertów we wszystkich tych frameworkach, wszystkie są dostępne w GitHub i mogą być ulepszane przez każdego, kto uważa, że ​​część kodu można zoptymalizować, aby działał szybciej.

Aktualizacja 3

Ember.js w przyszłych wersjach będzie zawierał szereg funkcji React, które są tutaj omówione (w tym wirtualny DOM i jednokierunkowe wiązanie danych, by wymienić tylko kilka), co oznacza, że ​​pomysły powstałe w React już migrują do innych frameworków. Zobacz: Droga do Ember 2.0 RFC - ciekawa dyskusja w żądaniu ściągnięcia Toma Dale'a (Data rozpoczęcia: 2014-12-03): „W Ember 2.0 wprowadzimy„ wirtualny DOM ”i model przepływu danych obejmujący najlepsze pomysły React i upraszcza komunikację między komponentami. ”

Również Angular.js 2.0 implementuje wiele omawianych tutaj pojęć.

Aktualizacja 4

Muszę rozwinąć kilka zagadnień, aby odpowiedzieć na ten komentarz Igwe Kalu:

„nie ma sensu porównywać React (JSX lub danych wyjściowych kompilacji) ze zwykłym JavaScriptem, gdy React ostatecznie redukuje się do zwykłego JavaScript. [...] Niezależnie od strategii, którą React używa do wstawiania DOM, można zastosować bez użycia React. nie dodaje żadnych specjalnych korzyści, gdy rozważa się omawianą funkcję inną niż wygoda ”. (pełny komentarz tutaj )

W przypadku, gdy nie było to wystarczająco jasne, w części mojej odpowiedzi porównuję wydajność działania bezpośrednio na natywnym DOM (zaimplementowanym jako obiekty hosta w przeglądarce) w porównaniu z fałszywą / wirtualną DOM React (zaimplementowaną w JavaScript). Chodzi mi o to, że wirtualny DOM zaimplementowany w JavaScript może przewyższać prawdziwy DOM zaimplementowany w C ++, a nie to, że React może przewyższyć JavaScript (co oczywiście nie ma większego sensu, ponieważ jest napisany w JavaScript). Chodzi mi o to, że „natywny” kod C ++ nie zawsze jest szybszy niż „nie-natywny” JavaScript. Wykorzystanie React do zilustrowania tego punktu było tylko przykładem.

Ale ten komentarz dotyczył interesującej kwestii. W pewnym sensie prawdą jest, że nie potrzebujesz żadnego frameworka (React, Angular lub jQuery) z jakiegokolwiek powodu (takiego jak wydajność, przenośność, funkcje), ponieważ zawsze możesz odtworzyć to, co robi dla ciebie frameworka i wymyślić koło - jeśli to znaczy uzasadnić koszt.

Ale - jak to ładnie ujął Dave Smith w: Jak pominąć punkt przy porównywaniu wydajności frameworka : „Porównując dwa frameworki, pytanie nie brzmi, czy moja aplikacja może być szybka z frameworkiem X. Pytanie brzmi: czy moja aplikacja będzie szybka z frameworkiem X. ”

W mojej odpowiedzi na 2011 r .: Jakie są niektóre empiryczne techniczne powody, aby nie używać jQuery , wyjaśniam podobny problem, że nie jest niemożliwe napisanie przenośnego kodu manipulacji DOM bez biblioteki takiej jak jQuery, ale ludzie rzadko to robią.

Podczas korzystania z języków programowania, bibliotek lub frameworków ludzie używają najwygodniejszych lub idiomatycznych sposobów robienia rzeczy, a nie idealnych, ale niewygodnych. Prawdziwą wartością dobrych frameworków jest ułatwienie tego, co w innym przypadku byłoby trudne do zrobienia - a sekret polega na tym, aby odpowiednie rzeczy były wygodne. W rezultacie nadal masz dokładnie taką samą moc, jak najprostsza forma rachunku lambda lub najbardziej prymitywna maszyna Turinga, ale względna ekspresja niektórych pojęć oznacza, że ​​te same pojęcia mają tendencję do wyrażania się łatwiej lub wcale, i że właściwe rozwiązania są nie tylko możliwe, ale faktycznie wdrażane na szeroką skalę.

Aktualizacja 5

React + Performance =? artykuł Paula Lewisa z lipca 2015 r. pokazuje przykład, w którym React działa wolniej niż waniliowy JavaScript napisany ręcznie dla nieskończonej listy zdjęć Flickr, co ma szczególne znaczenie na urządzeniach mobilnych. Ten przykład pokazuje, że każdy powinien zawsze testować wydajność dla konkretnego przypadku użycia oraz określonych platform docelowych i urządzeń.

Dziękuję Kevinowi Lozandierowi za zwrócenie mojej uwagi .

rsp
źródło
75
tak nazywam kompleksową odpowiedź, dzięki!
Demwunz
14
Wygląda na to, że Atom odchodzi od React. Zobacz github.com/atom/atom/issues/3677 .
Juho Vepsäläinen
6
@ash: Jeśli przeczytasz dalej wątek, będą mówić o tym, jak chcieliby w końcu całkowicie odejść od Reacta i innych frameworków, i po prostu rzucić własne przy użyciu niestandardowych elementów i cienia DOM.
musicfreak
3
Aby wyjaśnić powyższe sformułowanie, na liście @ErikAllik FRP (Functional Reactive Programming) nie jest nowym językiem, ale podejściem, które zyskuje na popularności. W rzeczywistości „Elm opiera się na pomyśle programowania funkcjonalnego reaktywnego” (z elm-lang.org) i, jak wspomniał, istnieją frameworki FRP dla Haskell itp.
Jon Coombs
5
tl; czytaj mimo wszystko - genialna, szczegółowa odpowiedź!
Mark K Cowan
16

Polimer jest niesamowity. React jest niesamowity. To nie to samo.

Polymer to biblioteka do tworzenia kompatybilnych wstecz komponentów internetowych.

React to V w MVC. To widok i nic więcej. Przynajmniej nie sam.

React nie jest ramą.

React + Flux + Node + (Gulp lub Grunt) jest bardziej podobny do frameworka, ale 3 z tych rzeczy wcale nie są częścią reakcji.

Istnieje wiele technologii, wzorów i stylów architektonicznych, które reagują deweloperzy, ale reakcja sama w sobie nie jest ramą.

To smutne, że nikt nie spieszył się z powiedzeniem najprostszej możliwej rzeczy, że nie należy ich porównywać. Mają pewne nakładki, ale różnią się bardziej niż to samo.

Oba pozwalają definiować komponenty sieciowe, ale na różne sposoby. Poza tym są to bardzo różne narzędzia.

Robotsushi
źródło
Czy nie reaguje zarówno na M, jak i na V, nie tylko na V, ponieważ przechowuje i aktualizuje stan danych oraz renderuje fragmenty HTML za pomocą komponentów?
abelito,
1
Istnieją biblioteki zarządzania stanem reagowania, takie jak flux lub redux, ale nie są one pakowane w program reagowania.
Robotsushi
Och, rozumiem, nie traktujemy Wyświetl danych jako danych modelowych ... dopóki nie zostaną przesłane po stronie serwera. Mimo że React przechowuje stan składnika (przeglądanie danych), pozostaje to przeglądać dane do momentu przesłania. To ma sens.
abelito
15

Chłopaki z React mają całkiem dobre wytłumaczenie na temat porównania między React i Web Components:

Próba porównania i kontrastu React z WebComponents nieuchronnie prowadzi do spekulacyjnych wniosków, ponieważ obie biblioteki są zbudowane w celu rozwiązywania różnych problemów. WebComponents zapewnia silną enkapsulację komponentów wielokrotnego użytku, a React zapewnia deklaratywną bibliotekę, która utrzymuje DOM w synchronizacji z Twoimi danymi. Te dwa cele się uzupełniają; inżynierowie mogą łączyć i dopasowywać technologie. Jako programista możesz swobodnie korzystać z React w swoich komponentach WebComponent, lub używać komponentu WebCompact w React lub obu tych metod.

Erik Allik
źródło
14

Inna odpowiedź w jednym punkcie, w szczególności:

Napisz JavaScript w waniliowym JavaScript, napisz CSS w CSS, napisz HTML w HTML.

Nic nie stoi na przeszkodzie, aby pisać Javascript w, powiedzmy, CoffeeScript, TypeScript, ClojureScript lub cokolwiek innego. To wyłącznie kwestia preferencji.

HTML to najlepszy DSL dla statycznych dokumentów HTML. Ale nie zapewnia nic dla dynamicznego HTML. W przeglądarce najlepszym językiem do dynamicznego HTML jest JavaScript, a nie czysty HTML z manipulacją DOM DOM w trybie ad-hoc lub język szablonów, taki jak kierownice, które nie są nawet półjęzykami.

W przypadku CSS, jeśli Twój CSS jest statyczny, piszesz go jak zwykle. Jeśli musi być dynamiczny w oparciu o niektóre wartości środowiska wykonawczego, jest to ta sama historia, co HTML: JavaScript jest najlepszym sposobem na jego dynamikę.

DjebbZ
źródło
1
Doceniam odpowiedź, ale tak naprawdę nie o to mi chodziło. Mam nadzieję, że moje zmiany sprawiły, że pytanie stało się nieco jaśniejsze?
CletusW
1
Przepraszam, że nie. Nadal możesz pisać swój styl w dowolnym języku stylów w osobnym pliku. A JSX Reacta sprawia, że ​​wygląda na to, że używasz języka znaczników.
DjebbZ
3
„JavaScript jest najlepszym sposobem na uczynienie [CSS] dynamicznym” - po prostu stwierdzenie, że tak naprawdę nie wyjaśnia dlaczego.
pilau
1
Cóż, jeśli style / klasy muszą się zmienić zgodnie z danymi wejściowymi użytkownika lub regułami biznesowymi, po prostu użyj javascript, aby je zmienić. W waniliowym js można manipulować właściwości classList lub stylów węzła DOM. Dzięki React możesz osiągnąć ten sam cel, manipulując wirtualnym DOM. Czy to jest jaśniejsze?
DjebbZ
2
Vjeux, główny współpracownik React, niedawno wygłosił mowę, w której popycha koncepcję „CSS w JS” za pomocą React. Myślę, że to ciekawe, możesz chcieć zobaczyć, o co chodzi: blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html
DjebbZ
6

Nie korzystałem ze składników WWW, ale wygląda na to, że wymagają dodania ręcznie kodowanej logiki mutacji do procedur obsługi zdarzeń.

fragment kodu z przykładu polimeru:

 <script>
   Polymer({
     counterChanged: function() {
       this.$.counterVal.classList.add('highlight');
     },
 ...

Celem React jest zmniejszenie złożoności poprzez wyeliminowanie logiki mutacji. Zamiast tego naiwnie regenerujesz wirtualny DOM i pozwalasz algorytmowi React na ustalenie, co należy zmienić w prawdziwym DOM.

limscoder
źródło
5
Nie wiem, skąd masz ten przykład, ale Polymer odradza również ręczną mutację DOM na korzyść wiązania danych, w tym nazw klas .
CletusW
Jest to przykład z zakładki „ Utwórz elementy” na stronie głównej polimer-project.org .
limscoder
4
Wow, masz rację! Sądzę, że chcieli tylko przykład automatycznego wyszukiwania węzłów. Jednak prawdopodobnie nie jest to najlepszy z możliwych.
CletusW,
6

Moim zdaniem największą wadą React jest to, że nie jest on oparty na standardach sieciowych. React jest w tej chwili bardzo potężnym narzędziem, ale ponieważ w miarę możliwości omija to, co zapewnia przeglądarka, decyzje, które wydawały się sensowne, prawdopodobnie nie będą miały sensu za kilka lat, ponieważ wbudowane funkcje przeglądarek nadal ulepszać. Chciałbym więc o tym porozmawiać i jak wpływa to na kilka różnych aspektów aplikacji internetowych.

Występ

Ludzie lubią argumentować, że zaletą React jest to, że całkowicie wymyśla cały model DOM i model zdarzeń, a istniejący standardowy DOM jest ciężki i drogi, a co nie, ale pod koniec dnia nie znalazłem wydajności React, aby być lepszym niż to, co mogę uzyskać z dobrze napisanej aplikacji Backbone lub Polymer. W rzeczywistości, przez większość mojego doświadczenia zawodowego, wydajność Reacta była nieco gorsza. Nie oznacza to, że React jest powolny ... To po prostu nie jest najnowocześniejszy wybór wydajności, jaki wszyscy myśleliśmy, że zanim go złapaliśmy.

W odpowiedzi rsp zwraca uwagę, że model DOM Reacta dla div ma znacznie mniejszą wagę niż natywny div DOM i to z pewnością jest prawda. Jednak aby React był użyteczny, ten „wirtualny” div musi w pewnym momencie stać się prawdziwym divem. Tak więc, moim zdaniem, nie jest to kwestia div React vs. div native. Jest to div React + native div vs. tylko native div. Narzut związany z wersją DOM programu React nie jest trywialny, a jeśli standardy kiedykolwiek upuszczą niektóre z tych niepotrzebnych atrybutów i pozwolą, aby natywne węzły DOM były znacznie lżejsze, nagle koszty te będą wydawać się naprawdę drogie.

W jednym z moich wcześniejszych miejsc pracy mieliśmy kilka aplikacji w Polimerze i kilka aplikacji w React. Jedna z wczesnych aplikacji Polymer została ostatecznie przepisana w React, ponieważ to było to, co firma miała standard, i na podstawie pomiarów wziąłem wersję React tej samej aplikacji, która zużyła około 30% więcej pamięci niż wersja Polymer , choć różnica była niewielka, wersja Polymer została również renderowana w krótszym czasie. Jedną rzeczą do rozważenia tutaj jest to, że mówimy o aplikacjach napisanych przez ludzi, a ludzie nie są doskonali, więc może być możliwe, że implementacja React tej aplikacji nie wykorzystywała wszystkiego, do czego React jest zdolny. Ale myślę, że przynajmniej część ma to związek z narzutem, jaki React wywołuje, mając własną wersję DOM.

React ponownie tworzy cały DOM przy użyciu własnego modelu, a następnie używa go do znacznej optymalizacji wydajności. Widok jest renderowany do wirtualnego DOM, który jest rzutowany do prawdziwej DOM. Gdy nastąpi zmiana i widok musi zostać zaktualizowany, widok jest ponownie świeżo renderowany ponownie do wirtualnej DOM, a drzewo to różni się od poprzedniego drzewa, aby określić, które węzły należy zmienić w prawdziwym DOM, aby odzwierciedlić tę zmianę w widoku. Chociaż jest to bardzo sprytne podejście do robienia wydajnych aktualizacji DOM, nadrzędnym jest utrzymywanie wszystkich tych wirtualnych drzew DOM i różnicowanie ich w celu określenia, co należy zmienić w prawdziwej DOM. W tej chwili narzut ten jest w dużym stopniu równoważony przez korzyści związane z wydajnością, ale wraz z poprawą natywnego DOM z czasem skala przesunie się w innym kierunku. Martwię się o to, jak aplikacje React mogą się starzeć, i jeśli za 3 lata będą znacznie wolniejsze niż rzeczy, które dotyczą DOM bardziej bezpośrednio. To wirtualne podejście DOM jest trochę młotem, a inne biblioteki, takie jak Polymer, są w stanie wdrożyć bardzo wydajne metody radzenia sobie z DOM w znacznie bardziej subtelny sposób.

Aktualizacja pod kątem wydajności: jedna z bibliotek, na które natknąłem się od dawna, robi to, co uważam za lepsze zadanie zarządzania aktualizacjami DOM. Jest to biblioteka Google Incremental Dom i myślę, że fakt, że działa ona z domem w miejscu i nie musi tworzyć „kopii wirtualnej”, jest znacznie czystszym podejściem i znacznie mniejszym obciążeniem pamięci. Zobacz więcej tutaj: http://google.github.io/incremental-dom/#about

Składniki deklaratywne a imperatywne

Jedną z rzeczy, które zawsze słyszysz, gdy mówisz o komponowaniu aplikacji, są wszystkie zalety deklaratywności komponentów. W światopoglądzie React wszystko jest ładne i deklaratywne. Piszesz JavaScript, który zwraca znaczniki, a React skleja to wszystko razem. I to świetnie, jeśli masz do czynienia z zupełnie nową aplikacją, która wykorzystuje tylko React i nic więcej. Możesz napisać jakiś komponent i dopóki jesteś w posiadanym przez React fragmencie DOM, jest to tak proste, jak umieszczenie tego tagu na stronie, aby zużył twój komponent.

Ale gdy tylko zabierzesz te komponenty i użyjesz ich poza Reactem, sytuacja stanie się znacznie bardziej chaotyczna. Ponieważ sposób, w jaki komponenty React są przekształcane w tagi, całkowicie wykracza poza to, co zapewniają standardy sieciowe, nic poza React nie wie, jak dać ci deklaratywny sposób wykorzystania tych komponentów. Jeśli chcę umieścić komponenty React w istniejącym widoku kręgosłupa korzystającym z szablonów Kierownic, musisz wyrenderować fikcyjny div w szablonie za pomocą klasy lub identyfikatora, którego można użyć jako uchwytu, a następnie napisać imperatywny JavaScript, aby znaleźć fikcyjną div i zamontować twój komponent w to. Masz aplikację Express.js korzystającą z szablonów po stronie serwera? To ta sama piosenka i taniec. Strona JSP? Śmiejesz się, ale wciąż korzysta z nich mnóstwo aplikacji. Jeśli nie jesteś startupem bez istniejącego kodu, „ Będę musiał napisać trochę hydrauliki, aby ponownie użyć komponentów React w wielu aplikacjach. Tymczasem Polymer osiąga komponenty za pomocą standardu Web Components, a korzystając ze specyfikacji elementu niestandardowego, Polymer jest w stanie tworzyć komponenty, które przeglądarka po prostu natywnie wie, jak je konsumować. Mogę umieścić składnik Polymer na stronie JSP, szablon Express.js, widok ASP.NET, widok Backbone ... nawet wewnątrz składnika React. Dosłownie wszędzie, gdzie można używać HTML, można spożywać składnik polimerowy. Ludzie zajmujący się inżynierią ponownego wykorzystania szukają standardów internetowych, ponieważ standardy są umową, która ułatwia wzajemne dostosowanie się. YouTube wciąż tworzy coraz więcej materiałów w Polymer (źródło: Polymer osiąga komponenty za pomocą standardu Web Components, a korzystając ze specyfikacji elementu niestandardowego, Polymer jest w stanie tworzyć komponenty, które przeglądarka natywnie wie, jak je konsumować. Mogę umieścić składnik Polymer na stronie JSP, szablon Express.js, widok ASP.NET, widok Backbone ... nawet wewnątrz składnika React. Dosłownie wszędzie, gdzie można używać HTML, można spożywać składnik polimerowy. Ludzie zajmujący się inżynierią ponownego wykorzystania szukają standardów internetowych, ponieważ standardy są umową, która ułatwia wzajemne dostosowanie się. YouTube wciąż tworzy coraz więcej materiałów w Polymer (źródło: Polymer osiąga komponenty za pomocą standardu Web Components, a korzystając ze specyfikacji elementu niestandardowego, Polymer jest w stanie tworzyć komponenty, które przeglądarka natywnie wie, jak je konsumować. Mogę umieścić składnik Polymer na stronie JSP, szablon Express.js, widok ASP.NET, widok Backbone ... nawet wewnątrz składnika React. Dosłownie wszędzie, gdzie można używać HTML, można spożywać składnik polimerowy. Ludzie zajmujący się inżynierią ponownego wykorzystania szukają standardów internetowych, ponieważ standardy są umową, która ułatwia wzajemne dostosowanie się. YouTube wciąż tworzy coraz więcej materiałów w Polymer (źródło: Mogę umieścić składnik Polymer na stronie JSP, szablon Express.js, widok ASP.NET, widok Backbone ... nawet wewnątrz składnika React. Dosłownie wszędzie, gdzie można używać HTML, można spożywać składnik polimerowy. Ludzie zajmujący się inżynierią ponownego wykorzystania szukają standardów internetowych, ponieważ standardy są umową, która ułatwia wzajemne dostosowanie się. YouTube wciąż tworzy coraz więcej materiałów w Polymer (źródło: Mogę umieścić składnik Polymer na stronie JSP, szablon Express.js, widok ASP.NET, widok Backbone ... nawet wewnątrz składnika React. Dosłownie wszędzie, gdzie można używać HTML, można spożywać składnik polimerowy. Ludzie zajmujący się inżynierią ponownego wykorzystania szukają standardów internetowych, ponieważ standardy są umową, która ułatwia wzajemne dostosowanie się. YouTube wciąż tworzy coraz więcej materiałów w Polymer (źródło:http://react-etc.net/entry/youtube-is-being-rebuilt-on-web-components-and-polymer ), i mogę sobie tylko wyobrazić, że aspekt polimeru oparty na standardach jest tego powodem. Ten odtwarzacz YouTube na środku strony YouTube może zostać przekształcony w komponent, który pobiera źródło treści jako właściwość, i nagle każdy, kto chce osadzić odtwarzacz YouTube na swojej stronie, może dosłownie użyć dokładnie tego samego kodu odtwarzacza, którego używa YouTube , i mogą to zrobić, po prostu umieszczając tag na swojej stronie.

Podsumowanie

Widzę, że zdecydowanie istnieją teraz atrakcyjne aspekty React. Jeśli wszystko, czego używasz, to React, możesz zbudować niektóre widżety i niektóre komponenty i deklaratywnie ponownie użyć ich w dowolnym miejscu. Sądzę jednak, że React byłby o wiele lepszy, gdyby użył niektórych standardów Web Components do osiągnięcia tego, co robi, zamiast iść i budować przeglądarkę w przeglądarce oraz skomplikowany mechanizm do synchronizacji wszystkiego.

Psy
źródło