ReactJSのリモートAJAXコンポーネント

ここでは、反応アプリケーション全体とは別に、リモート反応コンポーネントをロードしてレンダリングする方法について説明します! この問題をどのように解決したかを示します。 1年後、 react-remote-component-demo以外の同様のソリューションは見つかりません。



Reactでプロジェクトを開発するとき、タスクが設定されました。Reactの1ページのアプリケーションが追加コンポーネントをAJAXにロードして表示する必要があります。これらのコンポーネントは、アプリケーション自体に関係なくサーバー上で修正する必要がありました。


アプリケーションの構造は次のように簡略化されています。左側にコンポーネントのリストがあり、そのうちの1つをクリックすると、AJAXを介してリモートコンポーネントがロードされ、その詳細ビューが表示されます。


なぜなら 構築時にWebpackを使用しました。何かをグーグルで検索する最初の試みはrequire.ensureの使用につながりました


私の場合、これは不可能であることが判明しました。 Webpackのコンパイル時には、リモートコンポーネントの数はわかりません。コンポーネントが特定のフォルダーから静的に配布されるか、サーバーがデータベースからコンポーネントを配布することしかわかりません。


したがって、 CommonsChunkPluginを使用してwebpackに通知することは不可能であることが判明したため、これらの入力ファイルはそこに個別に配置する必要があります。 ファイルの数はわかりません。


合計で、reactアプリケーション自体はwebpackを使用して収集され、リモートコンポーネントは個別に準備されます(この場合、reactアプリケーション自体から削除されているため、このような定義を与えました)。


また、ES6でリモートコンポーネントを美しく書きたいと思いました。 そのため、リモートコンポーネントのコンパイル加えてBabelを使用する必要がありました。


試行錯誤を通じて、リモートコンポーネントをコンパイルすることができました。


コンポーネントは次のようになりました。


class CMP extends React.Component { constructor(props) { super(props); } render() { return <div> <div>Hello from <strong>FIRST</strong> remote component!</div> <div>{this.props.now}</div> </div> } } module.exports = CMP; 

これは、ソースリモートコンポーネント全体のリストであり、 import ... from ...または... = require(...) node_modulesからのnode_modules ... = require(...)でないため、機能しません。 さらに、 module.exports最後にあります。


ES6 1.jsxには、バブルの助けを借りてES5 1.jsでコンパイルできるコンポーネントがあります。


コンパイル後、 1.jsコンポーネントが1.jsたテキストファイルが完成し1.js


1.js
 "use strict"; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var CMP = function (_React$Component) { _inherits(CMP, _React$Component); function CMP(props) { _classCallCheck(this, CMP); return _possibleConstructorReturn(this, (CMP.__proto__ || Object.getPrototypeOf(CMP)).call(this, props)); } _createClass(CMP, [{ key: "render", value: function render() { return React.createElement( "div", null, React.createElement( "div", null, "Hello from ", React.createElement( "strong", null, "FIRST" ), " remote component!" ), React.createElement( "div", null, this.props.now ) ); } }]); return CMP; }(React.Component); module.exports = CMP; 

このファイルは、すでに静的に、またはデータベースから指定できます。


このファイルを反応アプリケーションにロードし、それからコンポーネントを作成し、レンダリングするために残ります。


これを行うコンポーネントはRemoteと呼ばれます。 リストを表示するには、 List呼び出しましょう。
ロジックは次のようなものです。Listはclickユーザーイベントをリッスンし、どのリスト項目がクリックされたかを判断します。したがって、このcomponentプロパティをpropsとしてRemoteに渡しcomponent
Remote内部Remoteは、 componentWillReceiveProps()関数を使用しました。 そのため、プロパティが変更されたと判断し、転送されたリモートコンポーネントの詳細ビューをレンダリングする必要があります。 これを行うには、コンポーネントキャッシュにあるかどうかを確認し、ない場合はロードします。


リモートコンポーネントを読み込むことは難しくありません(わかりやすくするために、 XMLHttpRequestの上位レベルのラッパーを使用しています)。
すべての魔法は次に起こります:


  ajax.load('/remote/' + requiredComponent) .then((str_component) => { let component; try { let module = {}, Template = new Function('module', 'React', str_component); Template(module, React); component = React.createFactory(module.exports); } catch (e) { console.error(e); } }) 

ロードされた行/コンポーネントから、テンプレート関数をnew Function()ます。 入力パラメーターとして、2つの文字列変数moduleReactを定義します。 このテンプレートTemplate(module, React) 「呼び出し」 Template(module, React)


新しいmodule = {}オブジェクトを作成し、それを最初の場所に渡し、reactモジュールを2番目の場所に渡します。


したがって、リモートコンポーネント内で記述した内容を思い出すと、次のようになります。


 ... extends React ... 

そして


 module.exports = ... 

関数/テンプレートを「呼び出す」とき、これらの2つの変数を渡します。エラーがないはずです。 これら2つの変数を定義しました。


その結果、オブジェクトmodule = {}結果はexportsプロパティに割り当てられます。 これが、 module.exportsReactを使用して、コンポーネントのコンパイル段階でエラーをバイパスするという2つの問題を解決する方法です。 そして、それらを入力パラメーターとして定義したので、ブラウザーで既にテンプレートを「実行」します。


コンポーネントcomponent = React.createFactory(module.exports)を作成し、レンダリングします。


  render() { let component = ...; return <div> {component ? component({ now: Date.now() }) : null} </div> } 

コンポーネントを呼び出すときに、 propsとして表示されるcomponent({ now: Date.now() })パラメーターを渡すことができます。


リモートコンポーネントはネイティブのように動作します!


要求されたアプリケーションのコードは、 react-remote-component githubに投稿されました:
開始するには、次を実行します。


npm installすべてのモジュールをインストール


npm run build-cmp 、リモートコンポーネントをdist/remoteコンパイルします


npm run server-dev webpack devサーバーnpm run server-dev起動します。これにより、アプリケーション全体がRAMに収集され、そこから配布され、削除されたコンポーネントが静的に配布されます。


ブラウザでhttp:// localhost:8099 /に移動します



Source: https://habr.com/ru/post/J319678/


All Articles