web-dev-qa-db-ja.com

React:DOM Reactがレンダリングしましたか?

これは私がやっていることです: jsfiddle

重要なセクションは次のとおりです。

position: function() {
  var container = $(this.getDOMNode());
  this._menu = $(this.refs.menu.getDOMNode());
  this._menu.appendTo(document.body).
      offset({
          top: container.offset().top + 
              container.outerHeight(),
          left: container.offset().left
      });
},
restore: function() {
  this._menu.appendTo(this.getDOMNode());      
},
componentWillUpdate: function() {
  this.restore();
},
componentDidUpdate: function() {
  this.position();
},
componentDidMount: function() {
  this.position();
},

これは今すぐにうまくいきます。 Reactは更新の間DOMをそのままにして、見逃さないという前提で、コンポーネントが更新される前にコンテンツを戻します。実際、Reactコンテンツの移動には問題ありません(componentWillUpdatecomponentDidUpdateを削除しても、配置された要素は更新されます!)

私の質問は、結果として生じる仮定のうちどれだけが安全であるかということです(つまり、これらのことを仮定すると、Reactの将来のバージョンでコードが壊れますか?):

  • Reactは、componentWillUpdateに戻す限り、更新間でDOMを移動してもかまいません。
  • Reactイベントハンドラーは、移動された要素に対して引き続き機能します。
  • Reactは、要求したインラインスタイルを要素に既に設定されているスタイルとマージします(設定していなくても)。
  • ドキュメント内の別の場所にDOMを移動しても、ReactはレンダリングしたDOMを更新します!

最後の1つはやや極端で魔法のように思えますが、それが成り立つ場合は大きな意味があります。

61
noah

私はReact開発者です。それぞれの質問に答えます:


ComponentWillUpdateに戻す限り、ReactはDOMを更新間で移動してもかまいません。

True-Reactは、イベントハンドラーを除き、更新時以外はDOMを参照しません。

Reactイベントハンドラーは、移動された要素に対して引き続き機能します。

私はこれに頼らないだろうし、それが今でも真実であるかどうか確信がない。

Reactは、要求したインラインスタイルを要素に既に設定されているスタイルとマージします(設定していなくても)。

私もこれに依存しません-現在Reactは個々のプロパティを設定しますが、_el.style.cssText_が設定されていると簡単に想像できます。

ドキュメント内の別の場所にDOMを移動しても、ReactはレンダリングしたDOMを更新します!

私はこれが現在真実であるとは思わないし、あなたもこれに頼るべきではない。


大まかに言って、Reactが作成したDOMを手で操作しないでください。 Reactで空の_<div>_を作成し、手で入力するのは100%正当です。後でReactでプロパティを変更しようとしない限り(ReactでDOM更新を実行する)、Reactでレンダリングされた要素のプロパティを変更しても問題ありませんが、要素、Reactはそれを探し、見つからない場合に混乱する可能性があります。

お役に立てば幸いです。

60
Sophie Alpert

一方では、実装の詳細に基づいて決定を下すべきではないという点でソフィーに同意します。ただし、Reactが実際にどのように機能するかを見るのはまだ面白いと思います。

いくつかのことが少し変わったかもしれませんが、一般的にこれは何が起こり、どのように起こるかです。

  1. Reactが作成するすべてのDOM要素に一意のID(現在はdata-attributes)を配置するという事実を考慮してください。これらのIDは現在、非常に単純なシステムに基づいています。これはシステムを説明するはずです-ルートノードは常に「.0」です

               .0
        .0.0        .0.1
    .0.0.0     .0.1.0 .0.1.1
    

「key」属性を指定すると、指定した値がリストのインデックスではなくidに使用されますが、システムは同じままです。

  1. Reactによって作成された仮想DOMには、同じIDの軽量オブジェクトもあります。これは、仮想DOMと実際のDOM間のシンプルなマッピングシステムです。

  2. これは、リストの途中で要素が追加または削除されると要素のidが変更されるため、「key」属性を指定しない場合、リスト内の要素が上書きされる理由でもあります。

それを覚えておいてください:

ComponentWillUpdateに戻す限り、ReactはDOMを更新間で移動してもかまいません。

はい。 ReactはIDを使用して機能するため、更新前に要素を戻さなくても、機能する可能性があると思います。しかし、要素を追加または削除したり、物事が壊れたりする可能性があるため、作業は非常にトリッキーで信頼性に欠けます。

Reactイベントハンドラーは、移動された要素に対して引き続き機能します。

はい...ある程度。反応のイベントハンドラーが機能する方法は、すべてのイベントが合成であるということです。これは、ReactルートDOMノードにイベントリスナーが1つしか存在しないことを意味します。そこでキャッチされたすべてのイベントは、Reactのイベントリスナーと照合されます。これも要素を一致させるためにIDを使用すると思います。ただし、Reactは、親要素の最小限のチェックを行う場合があります。 Reactによってレンダリングされた同じルートノード内に要素が保持されている限り、これは機能するはずです。とは言っても、Reactは将来idシステムを更新し、将来親ノードのより多くのチェックを行う可能性があり、これが壊れる可能性があります。

Reactは、要求したインラインスタイルを要素に既に設定されているスタイルとマージします(設定していなくても)。

これはすでに回答済みです。現在は動作しますが、将来は動作しない可能性があります。ただし、この実装の詳細に依存するアニメーションシステムがいくつかあるため、短期的には変更しません。

ドキュメント内の別の場所にDOMを移動しても、ReactはレンダリングしたDOMを更新します!

はい、同じreact-idで同じDOM要素を保持している場合、reactはドキュメント内で移動したことを認識せず、レンダリングしたのと同じ位置にあるかのように更新します。既にお気付きのように、同じReactルートにある必要があります。 Reactは合成イベントなどのReactルートDOMノードにのみバインドするため、これは重要です。このようにReactは他のライブラリとうまく連携し、ドキュメントルートにアクセスする必要はありません。

注意の言葉:何かをすることができるからといって、そうすべきだというわけではありません。一般的に、追加のDOMノードを追加し、Reactによって管理されていないDOMノードにプロパティを追加する必要があります(スタイル:変換値はアニメーションに共通です)。他のことをするとき、物事はうまくいくかもしれないことを理解してください。しかし、通常、物事を行うためのはるかに良い方法があります。


あなたの問題に関して:

では、私の問題をどのように解決しますか?たとえば、スクロール領域内のドロップダウンメニューがオーバーフローによって遮断される...エレメントを常にボディに移動しましたが、Reactの方法ではないようです。

ここでの理想的な状況は、まずドロップダウンを身体に入れることだと思います。次に、クリックイベントとドロップダウンの間でメッセージを渡すことができます。コールバックを使用して仮想DOMで十分に高くし、ドロップダウンまでプロップを更新してその状態を管理することができます。 OR良いol 'イベントシステムを使用してください。

17
Naman Goel