JSXの詳細
JSXはJavaScript文法の拡張であり、 XMLに似ています。 また、ReactでシンプルなJSX文法変換を使用することが出来ます。
何故JSXなのか?
ReactでJSXは必須ではありません。素のJavaScriptを使用しても問題ありません。 ただし、JSXが簡潔であり、また属性を伴うツリー構造を定義する際に、多くの人がこの書き事に慣れ親しんでいる点から、 我々はJSXの使用をお勧めしています。
デザイナーのような、時にカジュアルな開発者となる者にとっては、 この慣れ親しんでいるという利点は更に顕著になるでしょう。
XMLには「開きタグ」と「閉じタグ」という仕組みにより、バランスを保つ事が出来るという利点があります。 これは大規模なツリーにおいては、関数呼び出しやオブジェクト・リテラルよりも、構造を読みやすいものにしてくれます。
また、これはJavaScriptのセマンティクスを変更するものではありません。
HTML vs Reactコンポーネント
Reactは、HTMLタグ(文字列)またはReactコンポーネント(クラス)のどちらでも描画することが可能です。
var myDivElement = <div className="foo" />;
React.render(myDivElement, document.getElementById('example'));
Reactコンポーネントを描画するには、大文字で始まるローカル変数を作成するだけです。
var MyComponent = React.createClass({/*...*/});
var myElement = <MyComponent someProperty={true} />;
React.render(myElement, document.getElementById('example'));
ReactのJSXには、大文字と小文字を使用したローカル・コンポーネント・クラスとHTMLタグ識別の慣習があります。
注意:
JSXはJavaScriptである事から、XMLの属性名としてのclass
とfor
のような識別子が抑制されてしまいます。
代わりに、ReactのDOMコンポーネントは、それぞれclassName
とhtmlFor
のプロパティ名でそれを補います。
var myDivElement = <div className="foo" />;
React.render(myDivElement, document.getElementById('example'));
変換
ReactのJSXは、XML風の文法からネイティブなJavaScriptに変換されます。
XMLの要素、属性、そして子(要素)は、React.createElement
に渡される引数に変換されます。
var Nav;
// 入力 (JSX):
var app = <Nav color="blue" />;
// 出力 (JS):
var app = React.createElement(Nav, {color:"blue"});
<Nav />を使用するためには、スコープ内にNav変数が無ければいけないことに注意して下さい。
JSXもまたXML文法を使用した子の指定を許可します。
var Nav, Profile;
// Input (JSX):
var app = <Nav color="blue"><Profile>click</Profile></Nav>;
// Output (JS):
var app = React.createElement(
Nav,
{color:"blue"},
React.createElement(Profile, null, "click")
);
JSXはdisplayNameが割り当てられていない場合、変数への代入の記述からクラスのdisplayNameを推察します。
// Input (JSX):
var Nav = React.createClass({ });
// Output (JS):
var Nav = React.createClass({displayName: "Nav", });
JSXコンパイラを使用してJSXを試験し、 どのようにネイティブのJavaScriptに変換されるのか、 またHTML to JSX コンバーターがどのように既存のHTMLをJSXを変換するのかを確認してみて下さい。
もし、JSXを使用したいのであれば、 React入門でコンパイル環境のセットアップ方法を確認することが出来ます。
注意:
JSXの式は常にReactElementとして評価されます。
実際の実装の細部では、変更があるかもしれません。
最適化モードは、React.createElement
のバリデーション・コードを迂回するために、
オブジェクト・リテラルとしてReactElementへインライン化することが出来ました。(翻訳に自信なし)
コンポーネントの名前空間
もし、フォームのような多くの子要素を持つコンポーネントを構築する場合は、 最終的に多くの変数宣言をすることになるかもしれません。
// 煩雑な変数宣言ブロック
var Form = MyFormComponent;
var FormRow = Form.Row;
var FormLabel = Form.Label;
var FormInput = Form.Input;
var App = (
<Form>
<FormRow>
<FormLabel />
<FormInput />
</FormRow>
</Form>
);
これをよりシンプルで分かり易くするために、 コンポーネントに名前空間を割り当て、1つのコンポーネントが他のコンポーネントを属性として扱えるようにします。
var Form = MyFormComponent;
var App = (
<Form>
<Form.Row>
<Form.Label />
<Form.Input />
</Form.Row>
</Form>
);
これを行うために、主コンポーネントの属性として"副コンポーネント"を作成する必要があります。
var MyFormComponent = React.createClass({ ... });
MyFormComponent.Row = React.createClass({ ... });
MyFormComponent.Label = React.createClass({ ... });
MyFormComponent.Input = React.createClass({ ... });
JSXはコードのコンパイル時にこのプロパティを扱います。
var App = (
React.createElement(Form, null,
React.createElement(Form.Row, null,
React.createElement(Form.Label, null),
React.createElement(Form.Input, null)
)
)
);
注意:
この機能は、v0.11とそれ以降のバージョンで利用可能です。
JavaScriptの式
属性の式
属性の値としてJavaScript式を使用するために、
クォータ(""
)の代わりに中括弧({}
)のペアで式を囲みます。
// 入力 (JSX):
var person = <Person name={window.isLoggedIn ? window.name : ''} />;
// 出力 (JS):
var person = React.createElement(
Person,
{name: window.isLoggedIn ? window.name : ''}
);
子要素の式
同様に、JavaScriptの式は子要素での式として使用することが出来ます。
// 入力 (JSX):
var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
// 出力 (JS):
var content = React.createElement(
Container,
null,
window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
);
コメント
JSXにコメントを追加するのは簡単です。コメントは、JavaScriptのコメントがそのまま使用出来ます。
タグの子要素内では、コメントの両端に{}
を配置する必要があることに注意して下さい。
var content = (
<Nav>
{/* 子要素でのコメント、周りに{}を配置 */}
<Person
/* multi
line
comment */
name={window.isLoggedIn ? window.name : ''} // end of line comment
/>
</Nav>
);
注意:
JSXはHTMLと似ていますが、全く同じというわけではありません。
JSXの嵌まりどころで違いを確認して下さい。