ブラウザでの挙動について
Reactは多くのケースで直接DOMを触らなければいけないという問題から開発者を自由にするために、強力な抽象化を提供します。 ただし、時にはAPIの基盤部分に触らなければいけない事もあるでしょう。 それは、サードパーティ・ライブラリまたは既存コードと一緒に動かすような場合かもしれません。
バーチャルDOM
Reactが高速なのは、DOMとの直接的な対話をしないためです。
Reactは、DOMの高速なメモリ内表現を維持します。
render()
メソッドはDOMの記述を返し、
ブラウザを最速で更新する処理ために、
Reactはこの記述とメモリ内表現の差分を取ることが出来ます。
加えて、Reactは完全な人工的イベントシステムを実装しているため、 Quirksモードであっても全てのイベントオブジェクトがW3Cの仕様に従い、 クロスブラウザで全てのイベント伝搬(バブリング)の一貫性が保たれます。 IE8であっても、幾つかのHTML5イベントを使用することが可能です。
パーフォマンスと理解しやすさの点から、 あなたは多くの時間をこのReactの"擬似ブラウザ"の世界と共に過ごすべきでしょう。 ただし、時にはAPIの基盤部分に触らなければいけない事もあるでしょう。 それは、jQueryのようなサードパーティ・ライブラリ一緒に動かすような場合かもしれません。 Reactは基盤のDOM APIを直接使用するための脱出口を提供します。
参照とfindDOMNode()
ブラウザ上でインタラクティブな動作をするためには、DOMノードの参照が必要になります。
Reactには、コンポーネントのDOMノード参照を取得するためのReact.findDOMNode(component)
関数が用意されています。
注意:
findDOMNode()
はマウントされたコンポーネント(DOM内に配置されたコンポーネントのこと)上でのみ動作します。
もし、まだマウントされていないコンポーネント上でこれを呼び出そうとすると(作成されていないコンポーネント上のrender()
内でのfindDOMNode()
の呼び出し等)、
例外がスローされます。
Reactコンポーネントへの参照を取得するには、this
を使用して現在のReactコンポーネントを取得するか、
refs
を使用して、あなたが所有するコンポーネントを参照します。
これは次のように動作します。
var MyComponent = React.createClass({
handleClick: function() {
// 生のDOM APIを使用して、text inputを明示的にフォーカスします。
React.findDOMNode(this.refs.myTextInput).focus();
},
render: function() {
// ここでのref属性は、コンポーネントがマウントされた際に、
// this.refsへコンポーネントへの参照を追加します。
return (
<div>
<input type="text" ref="myTextInput" />
<input
type="button"
value="Focus the text input"
onClick={this.handleClick}
/>
</div>
);
}
});
React.render(
<MyComponent />,
document.getElementById('example')
);
参照の詳細
refs
について詳しく知りたければ、効果的な使用方法も含めて、
refsの詳細のドキュメントを参照して下さい。
コンポーネントのライフサイクル
コンポーネントには、主に3つのパートから成るライフサイクルがあります。
Reactは、このプロセスへのフックを指定することが出来るライフサイクル・メソッドを提供します。 我々は、何かが発生した直前に呼び出されるwillメソッドと、 何かが発生した直後に呼び出されるdidメソッドを提供します。
マウント(Mounting)
-
getInitialState(): object
コンポーネントがマウントされた後に実行されます。 ステートフルなコンポーネントは、これを実装し、初期のstateのデータを返すべきです。 -
componentWillMount()
は、マウントが発生する直前に実行されます。 -
componentDidMount()
は、マウントが発生した直後に実行されます。 DOMノードを必要とする初期化処理は、ここに入れる必要があります。
更新(Updating)
-
componentWillReceiveProps(object nextProps)
は、 マウントされたコンポーネントが新しいpropsを受け取った際に実行されます。 このメソッドは、this.setState()
を使用したstate
の変更を行うために、this.props
とnextProps
比較するのに使用されるべきです。 -
shouldComponentUpdate(object nextProps, object nextState): boolean
は、 コンポーネントが何らかの変更がDOMの更新をするか否かを決定する際に実行されます。this.props
とnextProps
、this.state
とnextState
の比較を最適化し、 Reactが更新をスキップする場合はfalseを返すものとして実装します。 -
componentWillUpdate(object nextProps, object nextState)
は、更新が発生する直前に実行されます。 ここで、this.setState()
を呼び出すことは出来ません。 -
componentDidUpdate(object prevProps, object prevState)
は、更新が発生した直後に実行されます。
アンマウント(Unmounting)
-
componentWillUnmount()
は、コンポーネントがアンマウント・削除の直前に実行されます。 ここでクリーンアップ処理を行うべきです。
マウントされたコンポーネントのメソッド
マウントされたコンポーネントは、下記のメソッドをサポートします。
-
findDOMNode(): DOMElement
は、マウントされたコンポーネント上で実行することで、 そこで描画されたDOMノードの参照を取得する事が出来ます。 -
forceUpdate()
は、マウントされたコンポーネント上で、 コンポーネントのstateのある重要な部分がthis.setState()
を使用せずに変更された事を把握している際に実行します。
ブラウザのサポートとPolyfills
Facebookでは、IE8を含む古いブラウザに対するサポートを行っています。
我々は長い間JSを前向きに書けるように、polyfillの準備を万全にしてきました。
これは、我々が基盤のコードを通した大量の散らかったハックが無く、
コードが「とにかく動く(just work)」ことを期待しているという事です。(翻訳に自信なし)
例えば、+new Date()
を参照する代わりに、Date.now()
と書くことが出来ます。
オープンソースのReactは内部的には同じことをしており、
JSを前向きに使用するための哲学をここにも持ち込んでいます。
この哲学には更に、JSライブラリの作者として、 我々がライブラリの一部としてpolyfillを取り入れるべきでは無いというスタンスもあります。 もし、各ライブラリがこれを行っていれば、同じpolyfillの重複を減らすことが可能になり、無駄なコードの削減に繋がります。 もし、あなたの製品が古めのブラウザをサポートする必要がある場合は、 es5-shimなどを常に使用する機会に恵まれることになります。
古いブラウザをサポートするためのPolyfill
kriskowal氏のes5-shimのes5-shim.js
は、
Reactが必要とする下記の機能を提供してくれます。
Array.isArray
Array.prototype.every
Array.prototype.forEach
Array.prototype.indexOf
Array.prototype.map
Date.now
Function.prototype.bind
Object.keys
String.prototype.split
String.prototype.trim
また、kriskowal氏のes5-shimのes5-sham.js
は、
Reactが必要とする下記の機能を提供してくれます。
Object.create
Object.freeze
minifiedされないReactのビルドでは、Reachは下記のpaulmillr氏のconsole-polyfillを必要とします。
console.*
IE8で<section>、<article>、<nav>、<header>、<footer>を含むHTML5要素を使用する際は、 html5shiv、 または同様のスクリプトも必須になります。
クロスブラウザ問題
Reactはブラウザ互換のための抽象化に非常に力を入れていますが、 一部のブラウザでは限界があったり、良い回避策を見つけることが出来ず、癖のある挙動の実装を行ったりしています。
IE8でのonScrollイベント
IE8上ではonScroll
イベントのイベント伝搬は発生せず、
またIE8は、イベントのフェーズをキャプチャリングするためのハンドラを定義するためのAPIを持ちません。
これは、Reactがこれらのイベントをリッスンする手段が無いことを意味します。
現在、このイベントのためのハンドラはIE8上では無視されます。
詳細については、GitHubのonScroll doesn't work in IE8のissueを参照して下さい。