업데이트 : 이 답변은 꽤 인기있는 것으로 보이므로 약간 정리하고 새로운 정보를 추가하고 충분히 명확하지 않은 것으로 생각되는 몇 가지를 명확히하는 데 시간이 걸렸습니다. 다른 설명이나 업데이트가 필요하다고 생각되면 의견을 말하십시오.
대부분의 우려 사항은 실제로 의견과 개인적 선호의 문제이지만 가능한 한 객관적으로 답변하려고 노력할 것입니다.
네이티브 대 컴파일
바닐라 JavaScript로 JavaScript 작성, CSS로 CSS 작성, HTML로 HTML 작성
위로 하루에 하나 작성해야하는지 여부 뜨거운 논쟁이 있었다 네이티브 손으로 조립 또는 컴파일러가 당신을 위해 어셈블리 코드를 생성하기 위해 C와 같은 높은 수준의 언어를 사용. 그 전에도 사람들은 어셈블러 에 대한 신뢰를 거부 하고 손으로 네이티브 머신 코드 를 작성하는 것을 선호했습니다 ( 그리고 나는 농담하지 않습니다 ).
한편, 오늘 HTML 쓰기 많은 사람들이 있습니다 HAML 또는 옥 에 CSS를 말대꾸 또는 이하 에서 자바 스크립트 커피 스크립트 또는 타이프 라이터가 . 저기에있어. 효과가있다. 어떤 사람들은 그것을 선호하지만 어떤 사람들은 그렇지 않습니다.
요점은 바닐라 JavaScript로 JavaScript를 작성 하지 않고 CSS로 CSS를 HTML로 HTML을 작성하는 데 근본적으로 잘못된 것이 없다는 것입니다 . 그것은 실제로 선호의 문제입니다.
내부 및 외부 DSL
대신 Shadow DOM React를 사용하는 스타일 캡슐화에는 JavaScript로 CSS를 작성해야합니다. 예쁘지 않은.
예쁘거나 말끔하게 표현 적입니다. JavaScript는 매우 강력한 언어로 CSS보다 훨씬 강력합니다 (CSS 전 처리기 포함). 그것은 일종의 내부 또는 외부 DSL을 선호하는지에 달려 있습니다. 다시, 선호의 문제.
(참고 : 원래 질문에서 참조 된 React 의 인라인 스타일에 대해 이야기했습니다 .)
DSL의 종류-설명
업데이트 : 답변을 작성한 후 얼마 후에 답변을 읽으면 여기서 의미하는 바를 설명해야한다고 생각합니다. DSL은 도메인 별 언어 이며 내부적이거나 (예 : JavaScript와 같은 호스트 언어의 구문을 사용하여 (예 : JSX가없는 React 또는 위에서 언급 한 React의 인라인 스타일과 같이)) 외부에있을 수 있습니다 (다른 구문을 사용) 이 예에서와 같이 호스트 언어보다 JavaScript 내에서 CSS (외부 DSL)를 인라인하는 것입니다.
일부 문헌에서는 이러한 종류의 DSL을 설명하기 위해 "내부"및 "외부"와 다른 용어를 사용하기 때문에 혼동 될 수 있습니다. 때때로 "내장"대신 "내장"이 사용되지만 "내장"이라는 단어는 다른 것을 의미 할 수 있습니다. 예를 들어 Lua 는 내장 (내장) DSL과 관련이없는 "루아 : 확장 가능한 내장 언어"로 설명 됩니다. 외부 DSL과 반대되는 개념이지만 SQLite가 내장 데이터베이스와 같은 의미로 내장되어 있음을 의미합니다. "e"가 세 번째 의미에서 "내장 된"을 의미하는 eLua 도 있습니다. 임베디드 시스템을 의미 합니다.! eLua와 같은 것은 "내장 된 DSL"이 아닌 두 가지 다른 의미로 "내장 된" "DSL"일 수 있기 때문에 "내장 DSL"이라는 용어를 사용하는 것을 좋아하지 않는 이유입니다!
상황을 악화시키기 위해 일부 프로젝트는 믹스에 더 많은 혼란을 초래합니다. 예 : Flatiron 템플릿 은 "DSL이없는"것으로 설명되어 있지만 실제로는 다음과 같은 구문을 가진 내부 DSL의 완벽한 예일뿐입니다.map.where('href').is('/').insert('newurl');
"JavaScript는 매우 강력한 언어이며 CSS보다 훨씬 더 강력한 언어입니다 (CSS 전 처리기 포함). 이는 일종의 내부 또는 외부 DSL을 선호하는지에 달려 있습니다. 선호의 문제 " 나는 그 두 가지 시나리오에 대해 이야기하고있었습니다.
하나:
/** @jsx React.DOM */
var colored = {
color: myColor
};
React.renderComponent(<div style={colored}>Hello World!</div>, mountNode);
두:
// SASS:
.colored {
color: $my-color;
}
// HTML:
<div class="colored">Hello World!</div>
첫 번째 예는 질문에서 "JavaScript로 CSS 작성. 예쁘지 않다"라는 설명을 사용합니다. 두 번째 예는 Sass를 사용합니다. CSS를 작성하기 위해 JavaScript를 사용하는 것은 ( "pretty"의 일부 정의에는) 좋지 않을 수 있지만 동의하면 한 가지 이점이 있습니다.
Sass에서 변수와 함수를 사용할 수 있지만 어휘 범위 또는 동적 범위가 있습니까? 정적으로 또는 동적으로 입력됩니까? 강하거나 약합니까? 숫자 형은 어떻습니까? 유형 강제? 어느 값이 진실하고 어떤 값이 거짓입니까? 고차 함수를 가질 수 있습니까? 재귀? 테일 전화? 어휘 폐쇄? 정상 순서 또는 적용 순서로 평가됩니까? 게 으르거나 열심 인 평가가 있습니까? 함수에 대한 인수가 값 또는 참조로 전달됩니까? 그들은 변할 수 있습니까? 불변? 지속성 있는? 객체는 어떻습니까? 클래스? 프로토 타입? 계승?
사소한 질문은 아니지만 Sass 또는 Less 코드를 이해하려면 답변을 알아야합니다. 나는 이미 JavaScript에 대한 답변을 알고 있으므로 React의 인라인 스타일과 같은 모든 내부 DSL을 이미 이해하고 있음을 의미하므로 React를 사용하면 그에 대한 답변 세트를 하나만 알아야합니다. ) 질문, 예를 들어 사용할 때 Sass와 Handlebars는 그런 세 가지 답변을 알고 그 의미를 이해해야합니다.
한 가지 또는 다른 방법이 항상 더 좋다고 말할 수는 없지만 다른 언어를 믹스에 도입 할 때마다 언뜻보기에는 분명하지 않을 수도있는 가격을 지불합니다.이 가격은 복잡합니다.
내가 원래 의미 한 바를 명확히했으면합니다.
데이터 바인딩
양방향 바인딩
이것은 정말 흥미로운 주제이며 실제로 선호도의 문제입니다. 양방향이 항상 단방향보다 낫지는 않습니다. 응용 프로그램에서 변경 가능한 상태를 모델링하려는 방법에 대한 질문입니다. 나는 항상 양방향 바인딩을 함수형 프로그래밍의 원칙에 다소 반대되는 생각으로 보았지만 함수형 프로그래밍은 작동하는 유일한 패러다임이 아니며 일부 사람들은 이런 종류의 행동을 선호하며 두 가지 접근 방식은 실제로는 잘 작동하는 것처럼 보입니다. React에서 상태 모델링과 관련된 디자인 결정의 세부 사항에 관심이 있다면 Pete Hunt (질문에 링크 됨)와 Tom Occhino와 Jordan Walke의 이야기를 잘 살펴보십시오. 내 의견.
업데이트 : Pete Hunt의 또 다른 이야기를 참조하십시오 : 예측 가능하고 정확하지 않습니다 : 기능적 DOM 프로그래밍 .
업데이트 2 : 많은 개발자들이 양방향 데이터 흐름 또는 양방향 바인딩 에 대해 논쟁 하고 있으며 일부는 반 패턴이라고도합니다. 예를 들어 가지고 플럭스 명시 적으로 방지 응용 프로그램 아키텍처 MVC의 엄격 단방향 데이터 흐름에 찬성 (대형 페이스 북과 인스 타 그램 애플리케이션을위한 확장하기 어려운 것으로 판명) 모델을합니다 (참조 페이스 북에 다시 생각 웹 응용 프로그램 개발 : 해커 웨이 에 의해 이야기 Tom Occhino, Jing Chen 및 Pete Hunt가 소개합니다. 또한 AngularJS 에 대한 많은 비판 (양방향 데이터 바인딩으로 알려진 MVC 모델을 기반으로 느슨하게 사용되는 가장 널리 사용되는 웹 프레임 워크)에는 해당 양방향 데이터 흐름에 대한 인수가 포함됩니다.
업데이트 3 : 위에서 논의 된 몇 가지 문제를 잘 설명하는 또 다른 흥미로운 기사는 ReactJS의 플럭스 분해-RefluxJS (Flux에서 영감을 얻은 단방향 데이터 흐름 응용 프로그램 아키텍처를위한 간단한 라이브러리)의 저자 Mikael Brassman의 ReactJS 와 함께 MVC를 사용하지 않음 입니다.
업데이트 4 : Ember.js 는 현재 양방향 데이터 바인딩에서 벗어나고 있으며 향후 버전에서는 기본적으로 단방향입니다. 참조 : 2014 년 11 월 15 일 토론토의 엠 베르 가르 텐 심포지엄에서 Stefan Penner 의 Ember 미래 이야기.
업데이트 5 : 참조 : The Road to Ember 2.0 RFC-Tom Dale의 풀 요청에 대한 흥미로운 토론 :
"원래 템플릿 레이어를 설계 할 때 모든 데이터 바인딩을 양방향으로 만드는 것은 그리 해롭지 않은 것으로 나타났습니다. 양방향 바인딩을 설정하지 않으면 사실상 일방적 인 바인딩입니다!
우리는 이후 React의 친구들의 도움을 받아 구성 요소가 변덕스러운 돌연변이를 경계하지 않고도 자녀에게 데이터를 전달할 수 있기를 원한다는 것을 깨달았습니다.
또한 구성 요소 간 통신은 가장 자연스럽게 이벤트 또는 콜백으로 표현됩니다 . 이것은 Ember에서 가능하지만 양방향 데이터 바인딩의 우세는 종종 사람들이 양방향 바인딩을 통신 채널로 사용하는 길을 안내합니다 . 숙련 된 Ember 개발자는 (보통)이 실수를하지는 않지만 쉽게 만들 수 있습니다. " [강조 추가]
기본 대 VM
기본 브라우저 지원 ( "더 빠른 것으로 보장"참조)
이제 마지막으로 의견이 아닌 무언가.
실제로 여기는 정확히 다른 방법입니다. 물론 "네이티브"코드는 C ++로 작성 될 수 있지만 JavaScript 엔진이 작성되었다고 생각하십니까?
사실 JavaScript 엔진은 오늘날 사용하는 최적화에서 정말 놀랍습니다 .V8뿐만 아니라 SpiderMonkey와 Chakra도 요즘 빛납니다. 그리고 JIT 컴파일러를 사용하면 코드가 가능한 한 기본적 일뿐만 아니라 정적으로 컴파일 된 코드에서는 수행 할 수없는 런타임 최적화 기회도 있습니다.
사람들은 JavaScript가 느리다고 생각할 때 일반적으로 DOM에 액세스하는 JavaScript를 의미합니다. DOM이 느립니다. C ++로 작성된 네이티브이지만 구현해야하는 복잡성 때문에 지옥만큼 느립니다.
콘솔을 열고 다음을 작성하십시오.
console.dir(document.createElement('div'));
div
DOM에 연결되지 않은 빈 요소가 구현해야하는 속성의 수를 확인하십시오 . 이것들은 "자신의 속성"인 첫 번째 레벨 속성입니다. 프로토 타입 체인에서 상속되지 않음 :
정렬, 대기 중, 볼륨 변경, 정시 업데이트, 일시 중단, 제출, 정지, 진행 중, 선택, 조회, 탐색, 진행 중, onresize, onreset, onratechange, 진행 중, 진행 중, 진행 중, 진행 중, onmousewheel, onmouseup, onmouseover, onmouseout, onmouseout, onmouseout, onmouseout onmouseenter, onmousedown, onloadstart, onloadedmetadata, onloadeddata, onload, onkeyup, onkeypress, onkeydown, oninvalid, oninput, onfocus, onerror, onended, onemptied, ondurationchange, ondrop, ondragstart, ondragover, ondragleave, ondragenter, ondragend, ondragend, ondragend, ondragend, ondragend, ondragend, ondragend, ondragend, ondragend, ondragend, ondragentd, ondragend, ondragentd, ondragend, ondragentd, ondragend, ondragentd, ondragentd, ondragend, ondragentd, ondragend, ondragend, ondragentd, ondragend, ondragentd, ondragentd, ondragend, ondragentd, ondragend oncontextmenu, onclose, onclick, onchange, oncanplaythrough, oncanplay, oncancel, onblur, onabort, 맞춤법 검사, isContentEditable, contentEditable, outerText, innerText, accessKey, hidden, webkitdropzone, 드래그 가능, tabIndex, dir, 번역, lang, title, childElementCount, lastElementChild,firstElementChild, children, nextElementSibling, previousElementSibling, onwheel, onwebkitfullscreenerror, onwebkitfullscreenchange, onselectstart, onsearch, onpaste, oncut, oncopy, onforeforee, onbeforecut, onbeforecopy, webkitShadowRoot, 데이터 세트, classList, className, outerHTML, innerHTML, scrollHeight, scrollWidth, scrollWidth, 스크롤 바퀴 clientHeight, clientWidth, clientTop, clientLeft, offsetParent, offsetHeight, offsetWidth, offsetTop, offsetLeft, localName, prefix, namespaceURI, id, style, attributes, tagName, parentElement, textContent, baseURI, ownerDocument, nextSibling, previousSibling, lastChild, firstChild, childNodes, parentNode, nodeType, nodeValue, nodeNameoncopy, onbeforepaste, onbeforecut, onbeforecopy, webkitShadowRoot, 데이터 세트, classList, className, outerHTML, innerHTML, scrollHeight, scrollWidth, scrollTop, scrollLeft, clientHeight, clientWidth, clientTop, clientLeft, offsetParent, offsetHeight, offsetWidth, offsetTop, offsetLeft, localName namespaceURI, id, 스타일, 속성, tagName, parentElement, textContent, baseURI, ownerDocument, nextSibling, previousSibling, lastChild, firstChild, childNodes, parentNode, nodeType, nodeValue, nodeNameoncopy, onbeforepaste, onbeforecut, onbeforecopy, webkitShadowRoot, 데이터 세트, classList, className, outerHTML, innerHTML, scrollHeight, scrollWidth, scrollTop, scrollLeft, clientHeight, clientWidth, clientTop, clientLeft, offsetParent, offsetHeight, offsetWidth, offsetTop, offsetLeft, localName namespaceURI, id, 스타일, 속성, 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
대부분은 실제로 중첩 된 객체 입니다. div
브라우저에서 빈 네이티브의 두 번째 수준 (자체) 속성을 보려면 이 바이올린을 참조하십시오 .
진심으로, 모든 단일 div 노드 에서 onvolumechange 속성을 의미 합니까? 실수입니까? 아니, 그것은 " 컨텐츠 속성과 IDL 속성 둘 다로서 모든 HTML 요소에 의해 지원 되어야 한다 "[강조된 HTML 스펙 6.1.6.2 ] 의 이벤트 핸들러 중 하나의 레거시 DOM 레벨 0 전통적인 이벤트 모델 버전 일 뿐이다. W3C에 의해-그 주위에 방법이 없습니다.
한편, 이들은 div
React에서 가짜 DOM의 첫 번째 레벨 속성입니다 .
props, _owner, _lifeCycleState, _pendingProps, _pendingCallbacks, _pendingOwner
큰 차이가 있지 않습니까? 실제로 이것은 JSON ( LIVE DEMO )으로 직렬화 된 전체 객체입니다 . 왜냐하면 원형 참조를 포함하지 않기 때문에 실제로 JSON으로 직렬화 할 수 있기 때문 입니다. 원래 DOM의 세계에서는 상상할 수없는 것 ( 예외가 발생합니다) ) :
{
"props": {},
"_owner": null,
"_lifeCycleState": "UNMOUNTED",
"_pendingProps": null,
"_pendingCallbacks": null,
"_pendingOwner": null
}
이것이 React가 네이티브 브라우저 DOM보다 빠를 수있는 주된 이유입니다. 왜냐하면 이 혼란 을 구현할 필요가 없기 때문 입니다.
참조 스티븐 Luscher하여이 프리젠 테이션은 C ++로 작성된 기본 DOM 또는 자바 스크립트로 작성 가짜 DOM : 빨리가 무엇인지 볼 수 있습니다. 매우 공정하고 재미있는 프레젠테이션입니다.
업데이트 : 향후 버전의 Ember.js 는 React에서 크게 영감을 얻은 가상 DOM을 사용하여 성능을 향상시킵니다. 참조 : 2014 년 11 월 15 일 토론토의 엠 베르 가르 텐 심포지엄에서 Stefan Penner 의 Ember 미래 이야기.
요약하자면 템플릿, 데이터 바인딩 또는 사용자 지정 요소와 같은 웹 구성 요소의 기능은 React에 비해 많은 이점이 있지만 문서 개체 모델 자체가 크게 단순화 될 때까지 성능이 그 중 하나가 아닙니다.
최신 정보
이 답변을 게시 한 지 두 달이 지났는데 여기에 관련된 뉴스가있었습니다. 방금 트위터에 글을 썼 듯이 JavaScript에서 GitHub가 작성한 Atom 텍스트 편집기 의 최신 버전 은 Facebook의 React를 사용 하여 Wikipedia에 따르면 "Atom은 Chromium을 기반으로하고 C ++로 작성되었습니다"라는 내용 에도 불구하고 더 나은 성능을 얻 습니다. 네이티브 C ++ DOM 구현 (참조 원자의 핵을 ) 과 자체 웹 브라우저와 함께 제공되므로 웹 구성 요소를 지원합니다. 웹 애플리케이션에서는 일반적으로 사용할 수없는 다른 종류의 최적화를 사용할 수 있었지만 Atom을 통해도 최고의 성능을 달성하기 위해 JavaScript로 작성된 React를 사용하기로 선택한 실제 프로젝트의 최신 예일뿐입니다. React로 시작하지는 않았으므로 사소한 변경은 아닙니다.
업데이트 2
이 토드 파커 흥미로운 비교 하여 WebPagetest을 의 성능을 비교하기 위해 TodoMVC의 각도, 백본 작성 예, 엠버, 폴리머, CanJS은, YUI, 마네는 반응 신발 끈. 이것은 내가 지금까지 본 가장 객관적인 비교입니다. 여기서 중요한 것은 모든 해당 예제가 모든 해당 프레임 워크의 전문가에 의해 작성되었으며 모두 GitHub 에서 사용할 수 있으며 일부 코드가 더 빨리 실행되도록 최적화 될 수 있다고 생각하는 사람이라면 누구나 향상시킬 수 있다는 것입니다.
업데이트 3
향후 버전의 Ember.js 에는 여기에서 논의되는 많은 React 기능 (가상 DOM 및 단방향 데이터 바인딩 포함)이 포함되어 React에서 시작된 아이디어가 이미 다른 프레임 워크로 마이그레이션되고 있음을 의미합니다. 참조 : The Road to Ember 2.0 RFC – Tom Dale의 풀 요청에 대한 흥미로운 토론 (시작 날짜 : 2014-12-03) : "Ember 2.0에서는"가상 DOM "및 데이터 흐름 모델을 채택 할 것입니다. "React의 최고의 아이디어로 부품 간의 커뮤니케이션을 단순화합니다."
또한 Angular.js 2.0 은 여기서 논의 된 많은 개념을 구현하고 있습니다.
업데이트 4
Igwe Kalu의 의견에 답하기 위해 몇 가지 문제를 자세히 설명해야합니다.
"React가 궁극적으로 일반 JavaScript로 감소 할 때 React (JSX 또는 컴파일 출력)를 일반 JavaScript와 비교하는 것은 합리적이지 않습니다. [...] React를 사용하지 않고 React를 적용 할 수있는 전략 React는 DOM 삽입에 사용할 수 있습니다. 편의성 이외의 문제를 고려할 때 특별한 이점이 없습니다. " (전체 의견은 여기에 )
그것이 명확하지 않은 경우, 내 대답의 일부로 네이티브 DOM (브라우저에서 호스트 객체로 구현)과 React의 가짜 / 가상 DOM (JavaScript로 구현)에서 직접 작동하는 성능을 비교하고 있습니다 . 내가 만들려고했던 점은 자바 스크립트로 구현 된 가상 DOM이 있다는 것입니다 수 있습니다 C ++에서 구현 된 실제 DOM을 능가하고 있지 그 (그것 때문에 분명 많은 이해가되지 것입니다 자바 스크립트를 능가 할 수 반작용 되는 자바 스크립트로 작성)를. 필자의 요점은 "네이티브"C ++ 코드가 "네이티브가 아닌"JavaScript보다 항상 빠르다는 보장은 없다. 요점을 설명하기 위해 React를 사용하는 것은 단지 예일뿐입니다.
그러나이 의견은 흥미로운 문제에 영향을 미쳤다. 어떤 의미에서든 성능, 이식성, 기능과 같은 어떤 이유로 든 프레임 워크 (React, Angular 또는 jQuery)가 필요하지 않다는 것은 사실입니다. 프레임 워크가 항상 자신을 위해하는 일을 다시 만들고 바퀴를 재발 명 할 수 있기 때문입니다. 즉, 비용을 정당화 할 수 있습니다.
그러나 데이브 스미스는 웹 프레임 워크 성능을 비교할 때 요점을 놓치는 방법에 대해 잘 설명했다 . "두 웹 프레임 워크를 비교할 때 문제는 내 앱이 프레임 워크 X로 빠를 수 없다는 것 입니다. 문제는 내 앱이 프레임 워크로 빠를 것입니다. 엑스."
년 내 2011 대답 : jQuery를 사용하지 않는 몇 가지 경험적 기술적 인 이유가 무엇 나는 jQuery를 같은 라이브러리없이 휴대용 DOM-조작 코드를 작성하는 것은 불가능 아니라고하지만, 사람들이 거의 그렇게 없다는 것을, 비슷한 문제를 설명합니다.
프로그래밍 언어, 라이브러리 또는 프레임 워크를 사용할 때 사람들은 완벽하지만 불편하지 않은 작업을 수행하는 가장 편리하거나 관용적 인 방법을 사용하는 경향이 있습니다. 좋은 프레임 워크의 진정한 가치는 그렇지 않은 일을 쉽게하는 것입니다. 비밀은 올바른 일을 편리하게 만들어줍니다 . 결과는 여전히 가장 간단한 형태의 람다 미적분학 또는 가장 원시적 인 튜링 머신과 동일한 힘을 그대로 유지하지만 특정 개념의 상대적 표현성은 그러한 개념이 더 쉽게 또는 전혀 표현되는 경향이 있음을 의미합니다. 올바른 솔루션은 가능할뿐만 아니라 실제로 광범위하게 구현됩니다.
업데이트 5
반응 + 성능 =? 2015 년 7 월 Paul Lewis의 기사는 React가 Flickr 그림의 무한 목록을 위해 직접 작성한 바닐라 JavaScript보다 느린 경우의 예를 보여줍니다. 특히 모바일에서 중요합니다. 이 예는 모든 사람이 특정 사용 사례와 특정 대상 플랫폼 및 장치에 대해 항상 성능을 테스트해야 함을 보여줍니다.
내 관심을 끌게 해준 Kevin Lozandier 에게 감사합니다 .