更新: この回答はかなり人気があるようですので、少し時間をかけて整理し、新しい情報を追加して、十分に明確ではないと思われるいくつかのことを明確にしました。他に説明や更新が必要だと思われる場合はコメントしてください。
あなたの懸念のほとんどは本当に意見と個人的な好みの問題ですが、私はできる限り客観的に答えようとします:
ネイティブとコンパイル済み
JavaScriptをバニラJavaScriptで記述し、CSSでCSSを記述し、HTMLでHTMLを記述します。
昔 、手作業でネイティブアセンブリを記述するか、Cのような高レベル言語を使用してコンパイラにアセンブリコードを生成させるかについての熱い議論がありました。その前でさえ、人々はアセンブラーを信頼することを拒否し、ネイティブのマシンコードを手で書くことを好みました(そして私は冗談ではありません)。
一方、今日でHTML書く人が多いHAMLやジェイドに、CSSをサスまたは少ない中およびJavaScript CoffeeScriptのか、活字体で。それはそこにあります。できます。好む人もいれば嫌いな人もいます。
要点は、バニラJavaScriptでJavaScriptを、CSSでCSSを、HTMLでHTMLを記述しないことに根本的な問題はないということです。それは本当に好みの問題です。
内部DSLと外部DSL
代わりにShadow DOM Reactを使用したスタイルのカプセル化にはこれがあり、JavaScriptでCSSを記述する必要があります。可愛くない。
かどうか、それは確かに表現力豊かです。JavaScriptは非常に強力な言語であり、CSSよりもはるかに強力です(CSSプリプロセッサを含む)。それは、これらの種類の内部DSLのどちらを優先するかによって異なります。繰り返しますが、好みの問題です。
(注:元の質問で参照されたReactのインラインスタイルについて話していました。)
DSLの種類-説明
更新:回答を書いてからしばらくしてから、ここで私が意味することを説明する必要があると思います。DSLはドメイン固有の言語であり、内部(JavaScriptなどのホスト言語の構文を使用-JSXなしのReactなど、または前述のReactのインラインスタイルのような)か、外部(異なる構文を使用)のいずれかです。ホスト言語よりも-この例のように、JavaScript内でCSS(外部DSL)をインライン化します)。
一部の文献では、これらの種類のDSLを説明するために「内部」および「外部」とは異なる用語を使用しているため、混乱を招く可能性があります。「内部」の代わりに「埋め込み」が使用されることもありますが、「埋め込み」という言葉は別の意味を意味する場合があります。たとえば、Lua は「Lua:拡張可能な組み込み言語」として記述されます。それはまったく反対です-外部DSL)が、SQLiteが組み込みデータベースであるという同じ意味で埋め込まれていることを意味します。第三の意味で「e」が「組み込み」を表すeLuaもあります。組み込みシステムを意味します!eLuaのようなものは、「埋め込みDSL」ではなく、2つの異なる意味で「埋め込み」される「DSL」になる可能性があるため、「埋め込みDSL」という用語を使用するのは好きではありません。
事態を悪化させるために、一部のプロジェクトでは、さらに混乱を招きます。例えば。Flatironテンプレートは「DSLフリー」と説明されていますが、実際には次のような構文を持つ内部DSLの完璧な例です。map.where('href').is('/').insert('newurl');
そうは言っても、「JavaScriptは非常に強力な言語であり、CSS(CSSプリプロセッサを含む)よりもはるかに強力です。これらの種類の内部DSLを優先するか外部DSLを優先するかによって異なります。好みの問題。」私はこれらの2つのシナリオについて話していました。
1:
/** @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を記述します。きれいではありません。」という質問で説明したものを使用します。2番目の例では、Sassを使用しています。JavaScriptを使用してCSSを記述することは(「かなり」の定義によっては)きれいではないかもしれませんが、それを行うことには1つの利点があります。
Sassで変数と関数を使用できますが、それらはレキシカルスコープまたはダイナミックスコープですか?それらは静的または動的に入力されますか?強くまたは弱く?数値型はどうですか?型強制?どの値が真実であり、どれが偽であるか?高階関数を使用できますか?再帰?テールコール?レキシカルクロージャー?通常の順序で評価されますか、それとも適用可能な順序で評価されますか?遅延評価または熱心な評価はありますか?関数への引数は、値または参照によって渡されますか?それらは変更可能ですか?不変?持続的?オブジェクトはどうですか?クラス?プロトタイプ?継承?
これらは些細な質問ではありませんが、Sass or Lessコードを理解したい場合は、それらに対する答えを知る必要があります。JavaScriptに対するそれらの回答は既に知っているので、それらのレベルでのすべての内部DSL(Reactのインラインスタイルなど)を既に理解しているので、Reactを使用する場合、それらに対する回答のセットを1つだけ知っている必要があります)質問、たとえば、SassとHandlebarsの場合、これらの答えの3つのセットを知り、その意味を理解する必要があります。
どちらかの方法が常に優れていると言うわけではありませんが、ミックスに別の言語を導入するたびに、一見すると明らかではないかもしれない価格を支払います。この価格は複雑です。
元々の意味を少し明確にしたいと思います。
データバインディング
双方向バインディング
これは本当に興味深いテーマであり、実際には好みの問題でもあります。双方向が常に一方向より優れているとは限りません。アプリケーションの可変状態をどのようにモデル化するのかという問題です。私は常に双方向バインディングを関数型プログラミングの原理に多少反するアイデアと考えていましたが、関数型プログラミングだけが機能するパラダイムではなく、一部の人々はこの種の動作を好み、両方のアプローチは実際にはかなりうまくいくようです。あなたは、見て反応における状態のモデリングに関する設計上の決定の内容に興味があるならピート・ハントで話を(質問ににリンクされている)とトムOcchinoとヨルダンWalkeによって話 に非常によくそれを説明します私の意見。
更新: Pete Huntによる別の講演も参照してください:予測できない、正しくない:機能的なDOMプログラミング。
アップデート2:多くの開発者が双方向データフロー、または双方向バインディングに反対していることを指摘する価値があります。FVCアプリケーションアーキテクチャを例に挙げて、MVCモデルを明示的に回避し(大規模なFacebookおよびInstagramアプリケーションではスケーリングが困難であることが判明した)、厳密に単方向のデータフローを優先します(Hacker Way:Rethinking Web App Development at Facebook talkを参照) Tom Occhino、Jing Chen、Pete Huntの優れた紹介)また、AngularJSに対する多くの批判 (双方向データバインディングで知られる、MVCモデルに大まかに基づいた最も人気のあるWebフレームワーク)には、その双方向データフローに対する引数が含まれています。
アップデート3:きれいに上記disscussedの問題のいくつかがされて説明するもう一つの興味深い記事ReactJSのフラックスを解体- ReactJSでMVCを使用していないミカエルBrassman、の著者によってRefluxJS(フラックスに触発された単方向のデータフローアプリケーションアーキテクチャのためのシンプルなライブラリ)。
更新4: Ember.jsは現在、双方向のデータバインディングを廃止し、将来のバージョンではデフォルトで一方向になります。参照:2014年11月15日にトロントで開催されたEmbergarten SymposiumのStefan PennerによるThe Future of Emberの講演。
更新5:参照: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にアタッチされていない空の要素が実装する必要があるプロパティの数を確認します。これらは、 「独自のプロパティ」である最初のレベルのプロパティです。プロトタイプチェーンから継承されない:
align、onwaiting、onvolumechange、ontimeupdate、onsuspend、onsubmit、onstalled、onshow、onselect、onseeking、onseeked、onscroll、onresize、onreset、onratechange、onprogress、onplaying、onplay、onpause、onmousewheel、onmouseup、onmouseover、onmouseout、onmousemove、onmouseove、onmousemove、onmouseove、onmousemove、onmouse onmouseenter、onmousedown、onloadstart、onloadedmetadata、onloadeddata、onload、onkeyup、onkeypress、onkeydown、oninvalid、oninput、onfocus、onerror、onended、onemptied、ondurationchange、ondrop、ondragstart、ondragover、ondragleave、ondragenter、ondragend、ondragend oncontextmenu、onclose、onclick、onchange、oncanplaythrough、oncanplay、oncancel、onblur、onabort、spellcheck、isContentEditable、contentEditable、outerText、innerText、accessKey、hidden、webkitdropzone、draggable、tabIndex、dir、translate、lang、title、childElementCount、lastElementChild、firstElementChild、children、nextElementSibling、previousElementSibling、onwheel、onwebkitfullscreenerror、onwebkitfullscreenchange、onselectstart、onsearch、onpaste、oncut、oncopy、onbeforepaste、onbeforecut、onbeforecopy、webkitShadowRoot、dataset、classList、className、outerHTML、innerHTML、scrollHeight、scrollWidth、scrollLeft、scrollLeft、scrollLeft 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、dataset、classList、className、outerHTML、innerHTML、scrollHeight、scrollWidth、scrollTop、scrollLeft、clientHeight、clientWidth、clientTop、clientLeft、offsetParent、offsetHeight、offsetWidth、offsetTop、offsetLeft、localName、prefix、 namespaceURI、id、スタイル、属性、tagName、parentElement、textContent、baseURI、ownerDocument、nextSibling、previousSibling、lastChild、firstChild、childNodes、parentNode、nodeType、nodeValue、nodeNameoncopy、onbeforepaste、onbeforecut、onbeforecopy、webkitShadowRoot、dataset、classList、className、outerHTML、innerHTML、scrollHeight、scrollWidth、scrollTop、scrollLeft、clientHeight、clientWidth、clientTop、clientLeft、offsetParent、offsetHeight、offsetWidth、offsetTop、offsetLeft、localName、prefix、 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
ブラウザで空のネイティブの第2レベル(独自の)プロパティを確認するには、このフィドルを参照してください。
私は真剣に、すべての単一divノードのonvolumechangeプロパティを意味しますか?それは間違いですか?いや、それは「イベントハンドラの1つだけのレガシーDOMレベル0の伝統的なイベントモデルのバージョンだしなければなりませんサポートされ、すべてのHTML要素での[強調追加]の両方のコンテンツの属性として、およびIDL属性」セクション6.1.6.2 HTMLの仕様の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またはJavaScriptで書かれた偽のDOM:速いがあるかを確認します。とても公平で楽しいプレゼンテーションです。
更新: 将来のバージョンのEmber.jsは、パフォーマンスを向上させるために、Reactに大きく影響された仮想DOMを使用します。参照:2014年11月15日にトロントで開催されたEmbergarten SymposiumのStefan PennerによるThe Future of Emberの講演。
要約すると、テンプレート、データバインディング、カスタム要素などのWebコンポーネントの機能には、Reactよりも多くの利点がありますが、ドキュメントオブジェクトモデル自体が大幅に簡素化されるまで、パフォーマンスはそれらの1つではありません。
更新
この回答を投稿してから2か月後に、関連するニュースがいくつかありました。私はちょうどTwitterで書かれている、の最新のバージョンのAtom JavaScriptでのGitHubによって書かれたテキストエディタには、Facebookの、より良いパフォーマンスを得るために反応使用していても、ウィキペディアによると、それは完全にコントロールを持っているので、「アトムはクロムに基づくものであり、C ++で書かれました」ネイティブC ++ DOM実装(参照アトムの核を)し、 独自のWebブラウザが付属しているため、Webコンポーネントのサポートが保証されています。これは、Webアプリケーションでは通常利用できない他の種類の最適化を使用できた現実世界のプロジェクトのごく最近の例であり、Atomにもかかわらず、最高のパフォーマンスを達成するためにJavaScriptで記述されたReactを使用することを選択しましたそもそもReactで構築されていなかったので、それを行うのは簡単な変更ではありませんでした。
更新2
Todd ParkerがWebPagetestを使用して、Angular、Backbone、Ember、Polymer、CanJS、YUI、Knockout、React、およびShoestringで記述されたTodoMVCサンプルのパフォーマンスを比較する興味深い比較があります。これは、これまで見てきた中で最も客観的な比較です。ここで重要なことは、それぞれの例はすべてこれらのフレームワークの専門家によって書かれたものであり、すべて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(JSXまたはコンパイル出力)を単純なJavaScriptと比較することは賢明ではありません。Reactが最終的に単純なJavaScriptに還元される場合。便利さ以外に問題の機能を検討する場合、特別な利点は追加されません。」(ここに完全なコメント)
十分に明確ではなかった場合、私の答えの一部として、ネイティブDOM(ブラウザーのホストオブジェクトとして実装)とReactの偽/仮想DOM(JavaScriptで実装)で直接操作するパフォーマンスを比較しています。私が作るしようとしていた点は、JavaScriptで実装された仮想DOMがあることであることができ、実際のC ++で実装DOMとアウトパフォームしませリアクト(それがあるため、明らかにあまり意味がありませんJavaScriptをアウトパフォームすることができますされて JavaScriptで記述されたが)。私のポイントは、「ネイティブ」C ++コードが「非ネイティブ」JavaScriptよりも高速であるとは限らないことです。Reactを使用してそのポイントを説明するのは単なる例です。
しかし、このコメントは興味深い問題に触れました。ある意味、フレームワーク(React、Angular、jQuery)が何らかの理由(パフォーマンス、移植性、機能など)で必要ないことは事実です。つまり、コストを正当化できます。
しかし-デイブスミスはきれいにそれを置くとして、Webフレームワークのパフォーマンスを比較するときのポイントを欠場する方法:「2つのWebフレームワークを比較すると、問題がないことができ、私のアプリは、フレームワークXと高速での質問はあります私のアプリは、フレームワークと高速でありますバツ。"
私の2011年の答え:jQueryのを使用しないように、いくつかの実証的、技術的な理由は何私はjQueryのようなライブラリせずにポータブルDOM-操作コードを記述することは不可能ではないことが、人々はほとんどそうしないことを、同様の問題を説明します。
プログラミング言語、ライブラリ、またはフレームワークを使用するとき、人々は物事を行うのに最も便利で慣用的な方法を使用する傾向があり、完璧ではなく不便な方法を使用します。優れたフレームワークの真の価値は、そうでなければ困難なことを簡単にすることであり、秘密は正しいことを便利にすることです。その結果、ラムダ計算の最も単純な形式または最も原始的なチューリングマシンとまったく同じ能力を自由に使用できますが、特定の概念の相対的な表現力は、それらの概念がより簡単に、またはまったく表現される傾向があることを意味し、適切なソリューションは単に可能であるだけでなく、実際に広く実装されています。
更新5
React + Performance =?2015年7月のPaul Lewisの記事は、ReactがFlickrの写真の無限リスト用に手書きで書かれたバニラJavaScriptよりも遅い例を示しています。これはモバイルで特に重要です。この例は、特定のユースケースと特定のターゲットプラットフォームおよびデバイスのパフォーマンスを誰もが常にテストする必要があることを示しています。
おかげケビンLozandierのための私の注意にそれを持って来ます。