Vibe.js-痛みを伴わない状態管理の試み

よ、ハラジテリ。







一般に、私はかなり長い間JavaScriptを書いてきましたが、最も重要なタスクの1つは常にアプリケーションの状態を整理することでした。

TL DR;

世界にはこれ以上馴染みのあるものはありません

自転車でホイールを書く方法







キャッシュしたいもの、更新するもの、どこでも更新するもの、ローカルコンポーネントだけでなく、ストア全体が変更された場合(Vuexに叫ぶ)にコンポーネント全体を再描画したくないが、使用するものにサブスクライブする(叫ぶMobX)。







Reduxでは、いくつかの点が本当に好きではありませんでした。







1)定型コードが多すぎる。 もちろん、プログラマーにとって突然変異をより快適にする方法やアプローチはたくさんありますが、それでもなお、この部分は私見で過負荷になっています。







2)エンティティの断片化。 かつて、ReactNativeでモバイルアプリケーションを作成したとき、JSON APIサーバーで作業しました。つまり、 json api仕様の形式で応答を返しました。これには、エンティティーとこれらのエンティティーの関係が含まれます。 この仕様は本当に気に入りましたが、最初は鈍くはしませんでした。 そしてすぐに問題の例:ダイアログのリストがあり、ダイアログに入りました-そこでユーザーはオンラインです。 ダイアログのリストに戻ります-ユーザーはオフラインです。 VKユーザーにはなじみがあると思います。







Vuexでは、原則としてすべてが好きですが、エンティティの断片化の問題はそこで解決されておらず、ニュアンスがあります。







Vibe.jsのアイデアは何ですか



概念実証を書いたとき、私は次のアイデアから始めました。







1)エンティティを1か所に配置したい。 データベースの場合:1 id = 1エンティティ。

2)必要なエンティティのみにサブスクライブできるようにしたい

3)同時に、必要なエンティティのサブスクリプションを毎回オフにしないように、さまざまなエンティティと属性を組み合わせたいと思います。

4)状態を直接リアクティブに更新できるようにしたいentity.name = "Vasiliy"



、同時にペイロードで突然変異を行い、少なくともテキストメッセージを追加するなど、何らかの方法で突然変異をデバッグできるようにしたい







どうした



Vibe.jsには次の概念があります。







モデル、EntitySubject



エンティティモデルを定義できるクラス。

使用例:







 const User = new Model('User', { structure: { name: types.Attribute, bestFriend: types.Reference('User'), additionalInfo: { age: types.Attribute } }, computed: { bestFriendsName(){ return this.bestFriend && this.bestFriend.name || "No best friend :C" } }, mutations: { setName(newName){ this.mutate({ name: newName }, "User.setName") } } });
      
      





コンストラクターを使用すると、エンティティの構造、計算値、および突然変異を記述することができます。

構造は、







またはネストされたオブジェクトを使用して記述できます。







ユーザー名は直接変更できることに注意してください: someUser.name = "New name"





しかし、突然変異はより標準化されたアプローチです。







モデルインスタンス自体はほとんど何も実行できません-コンストラクターからの構造のみを保存します。







エンティティを追加する場合:







 User.insertEntity(1, { name: "Yura", bestFriend: 1, // sad when the best friend of yourself is you additionalInfo: { age: 17 } });
      
      





値が指定されていない場合、デフォルトのnull



が使用されます。 このエンティティを使用するには、 observe



メソッドを呼び出します。







 const entity = User.observe(1); const user = entity.interface; console.log(user.name) // -> "Yura"
      
      





ニュアンスがありますよね? エンティティを操作するには、書きすぎることが多すぎます。 ライン上。







1) entity



= EntitySubject



インスタンス。 エンティティの変更をサブスクライブし、 interface



を更新しinterface



。 購読することもできます。

2) interface



=エンティティを操作するためのリアクティブインターフェイス。 彼には、エンティティの状態の値、計算値、および突然変異があります。 エンティティがEntityStore



まだ存在しない場合、 entity.interface



は「null」になることに注意してください。







EntityStore



名前が示すように、これはエンティティのリポジトリです。 すべての状態、すべてのobservable



、モデルを保存し、 Model



またはSubject



使用されるメソッドを含みます。







 const User = new Model('User', { structure: { name: types.Attribute, bestFriend: types.Reference('User'), additionalInfo: { age: types.Attribute } }, computed: { bestFriendsName(){ return this.bestFriend && this.bestFriend.name || "No best friend :C" } }, mutations: { setName(newName){ this.mutate({ name: newName }, "User.setName") } } }); const Store = new EntityStore([User]);
      
      





EntityStore



がすべての関係、リンク、サブスクリプションをリンクできるように、エンティティストアをモデルの配列で初期化します...







ディレクトリ、DirectorySubject



ディレクトリはエンティティ-シングルトーンに似ています。 識別子はなく、静的です。 また、エンティティはそれらをサブスクライブできないため、 EntityStore



初期化時に指定する必要はありません。 本質的に、ディレクトリは、属性とエンティティ参照の形で何らかのローカル状態を持つ「ディレクトリ」です。







たとえば、オンラインストアで本を見ると、そのようなディレクトリを使用できます。







 const Store = new EntityStore([Book]); const BooksList = new Directory('BooksList', { structure: { page: types.Attribute, searchWord: types.Attribute, fetchedBooks: types.Array(types.Reference(Book.name)) } }, Store);
      
      





ディレクトリは、計算された値と突然変異もサポートします。また、サブスクライブすることもできます。







サブスクリプションはどうですか?



Vibe.jsは、エンティティまたはディレクトリが、その状態で現在存在するエンティティにのみサブスクライブされるように編成されています。 つまり、ディレクトリに表示された要素の配列があり、それを置き換える場合、状態を変更した後、前の配列のエンティティからサブスクライブを解除し、新しいものにのみサブスクライブします。







さて、これはすべてテストされています。



またはすべてではありません。 私はテストを書くのが好きで、それをもっと書きたいと思っています。 その点で、彼らは間違って行くかもしれないすべてをカバーしていません。







参照資料



Githubライブラリリポジトリ







NPMモジュール







反応に関するTodoリストのあるリポジトリの例







ESDOCドキュメントが生成されたGithubページ








All Articles