プロキシの未来

画像






私たちプログラマーは夢想家です。 私たちはすべての問題を解決する新しい銀のプールを夢見て、誇大広告に従っています。 また、新しいバイクを作成することも大好きです。それにより、問題を解決するのではなく、新しいバイクを作成します。 この記事では、「疑似新」自転車を開発して、建築について少し考えてみましょう。



兄弟ReduxMobxなどに注目しながら 、現代的なアプローチを使用してアーキテクチャソリューションを開発してみましょう。



DropDownをアニメーション化するだけで以前は不必要だったJSが、予想外に強力な言語になったすばらしい時代になりました! 多数の興味深い新機能と再考された「古い」機能を備えています。 多くの場合、真っ先に進むのではなく、アーキテクチャを設計し、開発を容易にし、スケーラブルで消化しやすいコードを作成できるパターンとソリューションを適用します。



それでは始めましょう!



画像






私たちの自転車では、Viewをレンダリングせず、データとその変更に対する反応を保存するという問題を解決することをすぐに予約します。



未来はすでに来ています! ES2015 +があります! 彼と一緒に不思議な仕事をすることができます! しかし、待ってください...彼は私たちに何を与えますか? このような新しいスーパーバイクを使用して作成するには、すべての問題を確実に解決する必要がありますか?



プロキシを見てみましょう! プロキシは、削除、変更など、オブジェクトに対する操作を追跡する方法です。 IE11を除くすべての場所でプロキシがサポートされるようになり、Vue3は内部でそれを使用します。 さらに悪いことに、IE11がギャレーに残されたとしても、私たちはより明るい未来に向かって航海するでしょう。 要するに、サイクリングの最初の要素は-Proxyです。



ただし、 プロキシはすべての問題を解決するわけではなく、解決すべきではなく、オブジェクトとの相互作用を追跡する方法にすぎません。 お気に入りのソリューションのベストプラクティスを見てみましょう。



画像






Redux 、私たちはそれについて何が好きですか? アプリケーションのデータを格納する単一の場所は、すべての部分にロジックを広めることなく、1つの場所で変更を処理できます。 これはプラスです、それを取ります! ミドルウェアは、機能を拡張および補完し、ロギング、プロキシなどを編成できます。 いいね! しかし、 Redux 'aの主なプラスは、私にとってはシンプルさです。 そのため、私たちは自転車で、可能な限りすべてをシンプルにする必要があります。



マイナスのうち、これは非同期で動作します。 記述しなければならない余分なコードがたくさんあります...これをどうにかして避けなければなりません。



Mobxは、変更を追跡するための優れたソリューションです。 これはProxyを行います。 将来的に唯一のものは、ネストされた構造の操作方法Proxyに教えることです。



入力します。 今日、この人気のあるテーマを使用して、それを補足することもできればうれしいです。 ネストを考慮して、スーパーソリューションで実行時に入力と検証を行いましょう。



RxJS 、多くの場合、彼は私のために複雑な問題を解決できるという事実のために彼を愛していますが、それを実装する必要はありません。 決定を複雑にしないようにしますが、通常のJSオブジェクトを使用すると、必要に応じてRxが自転車で動作します。



React 、ここでさらに詳しく説明します。 Reactは重要なフレームワークです。 Reactの前に、EmberとAngular 1があり、コンポーネントアプローチの基本的な考え方を示しました。 コントローラー、サービスなどに集中していた基本的なロジックを補完する多くのコンポーネントとディレクティブを作成しました。 しかし、 Reactの出現により、同じコンテキストでHTMLから逃げることなく、アプリケーションをより宣言的に検討するようになり、構文を言うことができます。



コンポーネントアプローチの宣言的な性質は、すべてが可能な限り透明で明確になるように達成する必要があるものです。 トレンディなレンダープロパティは、ストリームから抜け出せず、ロジックをHOCよりも宣言的に記述する優れた機会を提供するので、それらを取り上げましょう。



全体の外観を大まかに理解したら、コードの記述を始めましょう。



画像






最新のフレームワークはそれぞれ独自の方法で優れています。 現在、状態を保存する問題を解決しています;実際、どこでも使用する必要があります。 たとえば、この記事では、 Reactを選択しました。 しかし理想的には、それは普遍的であるべきです。



StateManagerコンポーネントを作成します。 これは、 Reduxなど、アプリケーションのすべての状態を保存するメインコンポーネントです。 必要に応じて、検証( このソリューションなど )と類型化(TypeScript / Flow)を追加できます。 また、変更をプロキシの前、後、中に実行するオプションのミドルウェア機能を作成します。



statemanagerコンポーネント
class StateManager extends Component { componentWillMount() { this.data = this.props.data || {}; this.proxify({props: this, val: 'data'}); } proxify = ({props, val}) => { Object.keys(props[val]) .filter(prop => typeof props[val][prop] === 'object' || Array.isArray(props[val][prop])) .map(prop => ({props: props[val], val: prop})) .forEach(item => this.proxify(item)); props[val] = this._makeProxy(props[val]); }; _makeProxy = props => { return new Proxy(props, { set: (target, key, args) => { if (typeof args === 'object' || Array.isArray(args)) { target[key] = args; this.proxify({props: target, val: key}); } else { target[key] = args; } setTimeout(this.forceUpdate.bind(this)); return true; }, deleteProperty: (oTarget, key) => { setTimeout(this.forceUpdate.bind(this)); return true; } }); }; render() { return this.props.children(this.data); } } StateManager.propTypes = { data: PropTypes.object.isRequired };
      
      







順番に、ここで何が起こっているのか。 外部から、アプリケーションのデータ、またはプロセス中に入力する空のオブジェクト(回路)を転送します。 アプリケーションをラップします



StateManagerを使用する
 <StateManager data={{ state: {} }}> {store => ... … } </StateManager>
      
      







proxifyメソッドは、 _makeProxyメソッドを使用して、すべてのオブジェクト/配列をProxyに再帰的に変換し、変更の影響を受けやすくします。



プロキシオブジェクト自体に、変更用にset 、削除用にdeletePropertyの 2つのフックを追加しました。 セットでは、オブジェクト、配列、またはディープデータがある場合、 proxifyを介してそれらを再度実行し、 forceUpdateを呼び出します。これにより、アプリケーションの更新された状態ですべての子が再描画されます。



render-propを介して変更された状態を転送すると、アプリケーションの任意の部分に自動的に分散できます。



実際、これは通常のオブジェクトであるため、同じRxをそれに固定することができます。



速度では、プロキシされるオブジェクトは通常の割り当てとは大きく異なります。 彼は、ネストの深さが2であるオブジェクトの線の作成と割り当てを測定しました。



通常のオブジェクト用

〜0.006ms



プロキシ

〜0.05ms



これは通常の割り当てであり、反応などはありません。 これが最適化されることを期待しましょう。



数時間で「ひざまずく」で書かれたこの基本的なアプローチを使用すると、データが非同期で送信される予定リストを作成でき、要素の出力を制御できます。



やることリスト
 <StateManager data={{ state: {} }}> {store => <div> <button onClick={() => store.state = { todo: { items: [ {name: 'Get data', state: 'in-progress'}, {name: 'Bind proxy to all', state: 'in-progress'}, {name: 'Force update root component', state: 'in-progress'}, {name: 'Update data in children', state: 'in-progress'} ], filter: '' }} }>Load todolist</button> <hr/> <div> { store.state.todo && store.state.todo.items && [ <ul key="todolist"> { store.state.todo.items .map((item, index) => <li hidden={!(store.state.todo.filter === '' || item.state === store.state.todo.filter)} style={item.state === 'done' ? { textDecoration: 'line-through' } : {}} key={index}> {item.name} {item.state === 'done' ? <button onClick={() => store.state.todo.items[index].state = 'in-progress'}>Set to in progress</button> : <button onClick={() => store.state.todo.items[index].state = 'done'}>Set to done</button>} <button onClick={() => store.state.todo.items.splice(index, 1)}>Remove</button> </li> ) } </ul>, <div key="add-new"> <input type="text" ref={c => this.input = c} /> <button onClick={() => { if (this.input && !!this.input.value) { store.state.todo.items.push({name: this.input.value, state: 'in-progress'}); this.input.value = ''; } }}>Add new item</button> </div>, <select key="filter" onChange={e => store.state.todo.filter = e.target.value}> <option key="all" value="">All</option> <option key="in-progress" value="in-progress">In progress</option> <option key="done" value="done">Done</option> </select> ] } </div> <br/> <br/> <br/> <hr/> <h3>State:</h3> <pre>{JSON.stringify(store, true , 2)}</pre> </div> } </StateManager>
      
      







画像






この例では、 Proxyの使用に関するいくつかの考えといくつかの優れた実践例を共有したいと思います。 新しい標準を使用することで、JS動物園で価値のある完全なソリューションを作成できるようになることを願っています。 サイクリングの幸運を祈ります!



参照:



ソースコード

To-doリスト



All Articles