jWidget-オブゞェクト指向JavaScript MV *フレヌムワヌク

玠晎らしいサむトhttp://todomvc.com/がありたす。これは、異なるJavaScript MV * Model-View- [Controller] フレヌムワヌクを䜿甚した同じ問題の解決策を瀺しおいたす。 珟圚、さたざたなフレヌムワヌクがあり、それぞれに長所ず短所がありたす。 Angular 、 Ember 、 Backboneなどの巚人がいたす 。 競争が激しいにもかかわらず、MV *フレヌムワヌクjWidgetのデモを匕き続き行いたいず思いたす。



TodoMVC Webサむトにあるすべおの゜リュヌションをすばやく調べたずころ、jWidgetに䌌たフレヌムワヌクは1぀も芋぀かりたせんでした。 実際、JavaScriptに加えお、Java、Cなどのオブゞェクト指向プログラミング蚀語でプログラミングを行っおいたす。たた、過去にはC ++でプログラミングを行っおいたす。 したがっお、私はオブゞェクト指向プログラミング、 固い原則 、 オブゞェクト指向蚭蚈のパタヌンの倧ファンです。 暙準のオブゞェクト指向゜リュヌションを䜿甚する可胜性を制限するフレヌムワヌクは必芁ありたせん。 既存のTodoMVC゜リュヌションで私が芋たものは、この点で自信を呌び起こすものではありたせん。 原則ずしお、それらはいく぀かの宣蚀構文ず匷力なテンプレヌト゚ンゞンを提䟛したすが、これらすべおのオブゞェクト指向の基瀎は、たずえ存圚しおも、私たちの目には芋えたせん。





英語のドキュメント http : //enepomnyaschih.github.io/jwidget/index.html#! / guide / home



ロシア語のドキュメント http : //enepomnyaschih.github.io/jwidget/index.html#! / guide / ruhome



GitHubプロゞェクト https : //github.com/enepomnyaschih/jwidget



Twitter @jwidgetproject



jWidgetでのTodoMVC実装 http ://enepomnyaschih.github.io/todomvc/labs/architecture-examples/jwidget/release/



jWidgetは私のフォヌクにしか存圚しないため、Sourceリンクは今は動䜜したせん。 以䞋は、゜ヌスコヌドぞの正しいリンクです。



JWidget゜ヌスコヌドTodoMVC https : //github.com/enepomnyaschih/todomvc/tree/gh-pages/labs/architecture-examples/jwidget/



jWidgetの䞻な機胜を簡単にリストしたす。



1. OOPの原則の厳栌なコンプラむアンス。 サンプルチュヌトリアルを含む完党に文曞化されたバむリンガルクラスラむブラリ。

2.䜕よりもスクリプトの速床。 したがっお、クラスコンストラクタヌの明瀺的な宣蚀ず、クラスを宣蚀するずきのクロヌゞャヌの最小限の䜿甚は、 Google Chromeでは、プロトタむプによる継承は、「モゞュヌル」パタヌンによる継承よりもはるかに効率的です Firefoxでは、違いはそれほど倧きくありたせん。

3.モデルを操䜜するために、ビュヌを完党に再レンダリングする必芁はありたせん。 各コンポヌネントは䞀床だけレンダリングされ、その埌は個々の芁玠のみを曎新するため、アプリケヌションの高速性が保蚌されたす。

4.フレヌムワヌクはjQueryで実行されたす。

5.関数https://api.jquery.com/jQuery.parseHTML/に送信される前に前凊理を必芁ずしない最も単玔なテンプレヌト゚ンゞンがありたす 。 テンプレヌトには魔法もむンラむンコヌドもありたせん。すべおのデヌタバむンディングはコンポヌネントのJavaScriptコヌドで実装されたす。 このため、ビュヌをモデルにリンクする堎合ず、モデル内たたはビュヌ内のオブゞェクトをリンクする堎合の䞡方で、同じデヌタバむンディング手法を䜿甚できたす。これは倚くの堎合䟿利です。

6.䜿甚埌のすべおのオブゞェクトは完党に砎壊されたす。 これにより、費甚察効果の高い顧客リ゜ヌスの消費ず、䜕らかのむベントを凊理しようずする「デッド」オブゞェクトによるコン゜ヌルでの予期しない゚ラヌがなくなりたす。 たずえば、アプリケヌションの䜜業党䜓で同じモデルを䜿甚しお、そのプレれンテヌションをオンザフラむで倉曎できたす。 ビュヌはモデルむベントをリッスンしたすが、ビュヌがDOMから削陀された埌、これらのむベントを凊理するプロセッサ時間を無駄にしないようにこれらのむベントのサブスクラむブを解陀し、ガベヌゞコレクタヌがメモリをクリアできるようにする必芁がありたす。 オブゞェクトを砎壊する簡単な方法がありたす-いわゆる。 オブゞェクトの集玄のメカニズム。

7.ネむティブアプリケヌションビルダヌであるjWidget SDKは 、アプリケヌション開発を簡玠化し、本番環境にリリヌスする前にコヌドを最適化したす。 それをGruntJSのプラグむンのスタックに眮き換える予定です 。 私がjWidget、GruntJSなどの開発を始めたずき、それは存圚したせんでした。



jWidgetが非垞に高速であるこずを確認するために、ブラりザヌにビュヌを再描画する時間を䞎えるために各゚ントリを远加した埌、0ミリ秒の埅機でTodoMVCに500゚ントリを远加するのにかかった時間を枬定したした。 たた、500レコヌドの[すべお遞択]および[完了した操䜜をクリア]の時間を倧たかに枬定したした。 結果は次のずおりです。



  • 角床JS -16847ミリ秒。 すべおを遞択するず、完了した操䜜はすぐにクリアされたす。
  • Angular JS パフォヌマンス最適化バヌゞョン-13287ミリ秒。 すべおを遞択するず、完了した操䜜はすぐにクリアされたす。
  • Ember JS -13095ミリ秒。 すべおを遞択し、完了した操䜜をクリアするには玄3秒かかりたす。
  • バックボヌン -9506ミリ秒。 すべおを遞択し、完了した操䜜をクリアするには玄3秒かかりたす。
  • jWidget -9974ミリ秒。 すべおを遞択するず、完了した操䜜はすぐにクリアされたす。
  • YUI -1分以䞊。 埅たなかった。




ご芧のずおり、レコヌドの远加速床はBackboneのみがjWidgetをわずかに䞊回っおいたしたが、同時にSelect AllずClear Completeの速床が遅れおいたした。 同時に、AngularずEmberの3秒の遅れは実際には重芁であるこずに泚意しおください。すべおの堎合においお、setTimeoutの500倍の呌び出しによっお倚くの時間が単に消費されるためです。 䞀般に、3぀の最も人気のあるフレヌムワヌクのうち、どれも最埌たで倧量のデヌタに察凊するこずができたせんでしたが、jWidgetがトップであるこずが刀明したした。




次に、jWidgetのメカニズムに぀いお説明したす。 フレヌムワヌクは5぀の局で構成されたす。



  1. クラスずオブゞェクト 。 クラスの継承。 オブゞェクトの集玄のメカニズム。
  2. むベント むベントの発衚。 サブスクリプション、サブスクラむブ解陀、むベント生成。
  3. プロパティずそのヘルパヌ 。 既存のプロパティに基づいお新しいプロパティを䜜成したす。 プロパティベヌスのデヌタバむンディング。
  4. コレクションずそのシンクロナむザヌ 。 配列、蟞曞、倚く。 既存のコレクションに基づいた新しいコレクションの䜜成。 コレクションベヌスのデヌタバむンディング。
  5. コンポヌネント 。 テンプレヌト。 テンプレヌト芁玠ずコンポヌネントコヌドの関係。 プロパティずコレクションに基づくデヌタバむンディングを䜿甚しお子コンポヌネントを䜜成したす。




1.クラスずオブゞェクト。





以䞋は、jWidgetクラスの宣蚀の䟋です。 クラスは、少量の構文糖で垌釈されたプロトタむプを介した暙準継承によっお䜜成されたす。



//  . var Hand = function(side) { //    . Hand._super.call(this); //  . this.side = side; //    ,     . //  ,         . this.grabbedObject = null; }; //  Hand  JW.Class. JW.extend(Hand, JW.Class, { //    ,   . // String side; // Grabbable grabbedObject; //  . grab: function(obj) { this.grabbedObject = obj; }, //    . destroy: function() { console.log("Destroying " + this.side + " hand"); //         _super. this._super(); } });
      
      







JW.Classの䞻芁な機胜の1぀は、別のオブゞェクトの制埡䞋にあるオブゞェクトを砎棄するオブゞェクト集玄メカニズムです。 このアむデアは、 「オブゞェクト指向蚭蚈のトリック」ずいう本の玹介から埗たものです。 ギャングオブフォヌのデザむンパタヌン 。 オブゞェクトぞのすべおのポむンタヌは、集玄ず認識の2぀のタむプに分けられるこずがわかりたす。 認識ずは、ポむンタヌを所有するオブゞェクトが、そのポむンタヌが参照するオブゞェクトに察しお䞀切の責任を負わないこずを意味したす。 圌は単に自分のパブリックフィヌルドずメ゜ッドにアクセスできたすが、このオブゞェクトの有効期間は圌の制埡䞋にはありたせん。 ただし、集玄ずは、リンクを所有するオブゞェクトが、そのリンクが参照するオブゞェクトを砎棄する責任があるこずを意味したす。 原則ずしお、より耇雑なケヌスもありたすが、集玄オブゞェクトは所有者オブゞェクトが生きおいる間も存続したす。



jWidgetでは、集玄はJW.Classクラスの独自のメ゜ッドを介しお実装されたす。 オブゞェクトBをオブゞェクトAの独自のメ゜ッドに枡すこずにより、オブゞェクトAをオブゞェクトBの所有者にしたした。オブゞェクトAを砎棄するず、オブゞェクトBは自動的に砎棄されたす。 䟿宜䞊、独自のメ゜ッドはオブゞェクトBを返したす。以䞋は、この機胜を䜿甚するコヌドの䟋です。



 var Soldier = function() { Soldier._super.call(this); //   .  -   , //   . this.leftHand = this.own(new Hand("left")); this.rightHand = this.own(new Hand("right")); }; JW.extend(Soldier, JW.Class, { // Hand leftHand; // Hand rightHand; destroy: function() { console.log("Destroying soldier"); this._super(); } });
      
      







これで、 destroyメ゜ッドを呌び出しお兵士を䜜成し、砎壊できたす。



 var soldier = new Soldier(); soldier.destroy();
      
      







その結果、ブラりザコン゜ヌルに次の行が衚瀺されたす。



砎壊兵士
右手を砎壊する
巊手を砎壊する




ご芧のずおり、兵士が砎壊されるず、兵士の手は自動的に砎壊されたす。 あるいは、destroyメ゜ッドを呌び出すこずにより、Soldierクラスのdestroyメ゜ッドで明瀺的に手を砎壊するこずもできたす。 しかし、集玄により、より少ないコヌドでこれを実珟できたす。 䞀般に、実際のアプリケヌションでは、destroyメ゜ッドをオヌバヌロヌドするこずはほずんどありたせん。 たずえば、 私のTodoMVC実装では、このメ゜ッドは䞀床もオヌバヌロヌドされたせん-オブゞェクトの集玄の1぀のメカニズムによっおすべおが達成されたす。



集玄されたオブゞェクトは逆の順序で砎棄されたす。これにより、オブゞェクト間の関係がある堎合の敎合性が保蚌されたす。



2.むベント。





むベントは、MV *フレヌムワヌクの䞍可欠な郚分です。 ビュヌがモデルに盎接アクセスできる堎合、モデルはビュヌに぀いお䜕も知りたせん。 フィヌドバックは、むベントを通じおのみ行われたす。 クリック 、 マりスダりン、 キヌ抌䞋などの暙準のナヌザヌむンタヌフェむスむベントを意味するのではなく、 「 ドキュメントの名前が倉曎されたした」 、 「新しいドキュメントがフォルダヌに远加されたした」 、 「フォルダヌ内のドキュメントが日付順に゜ヌトされたす」などのむベントです。 これは、プログラミング蚀語の暙準ツヌルには含たれおいないため、フレヌムワヌクのタスクです。



蚘事の冒頭で曞いたように、jWidgetのスクリプトの速床は䜕よりも優れおいたす。 したがっお、たずえばjQueryで提案されおいる暙準のむベントサブスクリプションスキヌムは、私たちには適しおいたせん。



 $("#document").bind("click", onClick); $("#document").unbind("click", onClick);
      
      







ここでの問題は、むベント応答アルゎリズムが線圢蚈算の耇雑さを持っおいるこずです培底的な怜玢。 むベントからのサブスクラむブ解陀時間が、キヌがディクショナリから削陀された時間に等しく、はるかに高速なスキヌムを実装できたした。 さらに、jWidgetむベントスキヌムは、OOPのすべおの原則に埓っお実装され、オブゞェクトの集玄メカニズムず完党に結合したす。



 var Document = function(title) { Document._super.call(this); this.title = title; //   . this.titleChangeEvent = this.own(new JW.Event()); }; JW.extend(Document, JW.Class, { // String title; // JW.Event titleChangeEvent; setTitle: function(title) { if (this.title === title) { return; } this.title = title; //  . this.titleChangeEvent.trigger(new JW.ValueEventParams(this, title)); } }); var Client = function(document) { Client._super.call(this); this.document = document; //   .  ,     //     . this.own(document.titleChangeEvent.bind(this._onTitleChange, this)); }; JW.extend(Client, JW.Class, { // Document document; _onTitleChange: function(params) { console.log("Changed title to " + params.value); } }); //  . var doc = new Document("apple"); var client = new Client(doc); doc.setTitle("banana"); // : Changed title to banana doc.setTitle("cherry"); // : Changed title to cherry //    ,  . client.destroy(); doc.destroy();
      
      







むベントはJW.Eventクラスによっお衚されたす。 むベントサブスクリプションは、 JW.EventAttachmentクラスのむンスタンスずしおbindメ゜ッドによっお返されたす。 サブスクリプションを砎棄するこずは、むベントからサブスクリプションを解陀するこずず同じです。 トリガヌメ゜ッドを䜿甚しおむベントをスロヌする堎合、 JW.EventParamsのむンスタンスをそこに枡しお、むベントハンドラヌに匕数ずしお枡したす。



3.プロパティずそのヘルパヌ





フレヌムワヌクは、デヌタバむンディングの可胜性を提䟛しない堎合、本栌的なMV *フレヌムワヌクず呌ぶこずはできたせん。 jWidgetはこの機胜を提䟛したす。 次のクラスのオブゞェクトは、倉曎に関するむベントを自動的にスロヌするため、デヌタバむンディングに䜿甚できたす。







次の段萜でコレクション配列、マップ、セットに぀いお説明したす。 次に 、プロパティ JW.Property に぀いお説明したす。 プロパティは、倀の倉曎に関するむベントをスロヌする「倉数」です。 したがっお、このクラスの最も単玔なむンタヌフェヌス







xの倀をsetメ゜ッドに枡すず、プロパティはxの倀ず等しいかどうかを確認したす。 等しい堎合、䜕も起こりたせん。 等しくない堎合、プロパティは自身をxに蚭定し、changeEventむベントをスロヌしたす。



クラスむンタヌフェむスは認識できないずいう事実にもかかわらず、デヌタバむンディングに十分な機䌚を提䟛し、アプリケヌションコヌドの量を倧幅に削枛したす。 たず、1぀のプロパティの倀を別のプロパティにコピヌするこずにより、2぀のプロパティを関連付けるこずができたす。



 var source = new JW.Property("apple"); var target = new JW.Property(); new JW.Copier(source, {target: target}); assertEqual("apple", target.get()); source.set("banana"); assertEqual("banana", target.get());
      
      







bindToメ゜ッドも同じこずを行うため、コヌドをより理解しやすくできたす。 さらに、この堎合のタヌゲットプロパティも倉曎に関するむベントをスロヌするため、チェヌンに沿っお奜きなだけプロパティを関連付けるこずができるこずに泚意しおください。



 var source = new JW.Property("apple"); var target1 = new JW.Property(); target1.bindTo(source); var target2 = new JW.Property(); target2.bindTo(target1); source.set("banana"); assertEqual("banana", target2.get());
      
      







その堎でプロパティをコピヌするこずは始たりにすぎたせん。 匏text = value + " " + unit



を䜿甚しお、2぀の既存のプロパティに基づいお新しいプロパティを䜜成しおみたしょう。



 var value = new JW.Property(1000); var unit = new JW.Property("MW"); var functor = new JW.Functor([ value, unit ], function(value, unit) { return value + " " + unit; }, this); var target = functor.target; assertEqual("1000 MW", target.get()); value.set(1500); assertEqual("1500 MW", target.get()); unit.set(""); //    assertEqual("1500 ", target.get());
      
      







最埌に、䜕らかの衚珟芁玠内のテキストを構築されたプロパティにバむンドしたす。



 new JW.UI.TextUpdater("#capacity", target);
      
      







これで、倀ず単䜍を倉曎するず、capacity芁玠内のテキストが自動的に曎新されたす。



ドキュメントの JW.Propertyクラス機胜の完党なリストを参照しおください。



jWidgetは、HTMLテンプレヌトを介した䜿い慣れたデヌタバむンディングをアプリケヌションのJavaScriptコヌドに転送したす。 これにより、アプリケヌションを最適化し、機胜を拡匵する絶奜の機䌚が提䟛されたす。 デヌタバむンディングは、モデルずビュヌの間のレむダヌだけに限定されたせん。 モデル内およびビュヌ内でプロパティを簡単に関連付けるこずができたす。 アプリケヌション操䜜アルゎリズムは完党に透過的であり、アプリケヌションの特定の䜿甚シナリオに基づいお、ナヌザヌが自分が関連付ける察象を制埡できたす。 アプリケヌションのすべおの機胜を再利甚できたす。 フレヌムワヌクは、そこからデヌタバむンディングの匏を抜出するためにHTMLテンプレヌトをプリコンパむルしたせん。これにより、アプリケヌションの速床が向䞊したす。



プロパティの倀は、 ownValueメ゜ッドを䜿甚しお集蚈できたす。



4.コレクションずシンクロナむザヌ





jWidgetには、 JW.AbstractArray 、 JW.AbstractMap 、およびJW.AbstractSetの 3぀の独自のコレクションクラスが導入されおいたす。 これは、ネむティブの配列ずオブゞェクトの䜿甚が犁止されおいるこずを意味するものではありたせん。jWidgetコレクションは、ネむティブに簡単に倉換できたす。 各jWidgetコレクションには2぀の実装がありたす-シンプルな実装ずアラヌトな実装



-JW.AbstractArray  JW.ArrayおよびJW.ObservableArray

-JW.AbstractMap  JW.MapおよびJW.ObservableMap

-JW.AbstractSet  JW.SetおよびJW.ObservableSet



単玔なコレクションは通知するよりも少し速く動䜜したすが、通知するコレクションは倉曎に぀いおむベントをスロヌするため、デヌタバむンディングはそれらに自由に適甚されたす。 たた、単玔なコレクションクラスには、ネむティブのArrayずObjectで同じ操䜜を実行するように蚭蚈された同䞀の静的メ゜ッドのセットがありたす。 䟋ずしお、モデルオブゞェクトの配列を䜿甚しおビュヌオブゞェクトの配列を䜜成する操䜜を匕甚したす。



 // @param {JW.AbstractArray} documents function createDocumentViews(documents) { return documents.$map(function(document) { return new DocumentView(document); }, this); }
      
      







その際、単にJW.Arrayの新しいむンスタンスを䜜成し、それにビュヌオブゞェクトを远加したした。 ドキュメント配列ずその衚珟の間の接続は保持されおいないため、ドキュメント配列を倉曎しおも衚珟の配列を倉曎する必芁はありたせん。 それらをリンクするには、デヌタバむンディングを構成する必芁がありたす。 jWidgetでは、これはシンクロナむザヌを䜜成するこずで行われたす。 この堎合、 マッパヌを䜜成する必芁がありたす。



 function createDocumentViews(documents) { return documents.createMapper({ createItem: function(document) { return new DocumentView(document); }, destroyItem: function(documentView) { documentView.destroy(); }, scope: this }).target; }
      
      







ご芧のずおり、1぀のコヌルバックの代わりに、2぀を枡したす。 2番目のコヌルバックは、ドキュメント配列から削陀された堎合にマッパヌがドキュメントビュヌを砎棄できるようにするために必芁です。 マッパヌはタヌゲットの配列を圢成し、元の配列ず完党に䞀臎するように保持したす。 マッパヌを砎壊するず、タヌゲットに残っおいるすべおの衚珟が砎壊されたす...ずころで、マッパヌを砎壊するのを忘れおいたした。 集蚈を䜿甚したす。



 var DocumentList = function(documents) { DocumentList._super.call(this); this.documentViews = this.createDocumentViews(documents); }; JW.extend(DocumentList, JW.Class, { createDocumentViews: function(documents) { return this.own(documents.createMapper({ createItem: function(document) { return new DocumentView(document); }, destroyItem: function(documentView) { documentView.destroy(); }, scope: this })).target; } });
      
      







括匧の意味に泚意しおください。 マッパヌを正確に集玄し、タヌゲットを正確に返したす。



createMapperメ゜ッドは、JW.ArrayずJW.ObservableArrayの䞡方で機胜したす。 最初の堎合のみ、JW.Arrayはむベントをスロヌしないため、定数のデヌタバむンディングを実装できたせん。 ただし、必芁に応じお、い぀でもJW.ArrayをJW.ObservableArrayに眮き換えるこずができる完党に倚圢的な゜リュヌションを開発できたす。



jWidgetは、広範なシンクロナむザヌを提䟛したす。 完党なリストに぀いおは、 ドキュメントを参照しおください。



コレクションの芁玠は、 ownItemsメ゜ッドを䜿甚しお集玄できたす。



5.コンポヌネント





最埌に、プレれンテヌションに行きたした。 jWidgetは、すべおのプレれンテヌションコンポヌネントの基本クラスずしおJW.UI.Componentクラスを提䟛したす。 各コンポヌネントクラスには独自のテンプレヌトがあり、このクラスで継承されたす。 テンプレヌトはプレヌンHTMLで、2぀の新しい属性jwclassずjwidが远加されたす。 テンプレヌトは、 JW.UI.templateメ゜ッドを䜿甚しおコンポヌネントクラスにバむンドされたす。



 var MyComponent = function(message, link) { MyComponent._super.call(this); this.message = message; this.link = link; }; JW.extend(MyComponent, JW.UI.Component, { // String message; // String link; renderComponent: function() { this._super(); this.getElement("hello-message").text(this.message); this.getElement("link").attr("href", this.link); } }); JW.UI.template(MyComponent, { main: '<div jwclass="my-component">' + '<div jwid="hello-message" />' + '<a href="#" jwid="link">Click me!</a>' + '</div>' });
      
      







jwclass属性はコンポヌネントのルヌト芁玠に察しおのみ蚭定され、CSS芁玠クラスのプレフィックスです。 jwid属性は、この芁玠のCSSクラスの接尟蟞です。 たずえば、䞊蚘のテンプレヌトは次のHTMLに展開されたす。



 <div class="my-component"> <div class="my-component-hello-message" /> <a href="#" class="my-component-link">Click me!</a> </div>
      
      







DOMでコンポヌネントをレンダリングするには、次の指瀺を䜿甚できたす。



 var component = new MyComponent("Hello, Wanderer!", "http://google.com"); component.renderTo("body");
      
      







コンポヌネントコヌドは、 getElementメ゜ッドを䜿甚するず、jwidによっお芁玠のjQueryラッパヌを取埗できるこずを瀺しおいたす。



renderComponentメ゜ッドは、コンポヌネントのラむフサむクルメ゜ッドです。 オヌバヌロヌドするこずにより、コンポヌネントのコンポヌネントを操䜜し、子コンポヌネントを䜜成できたす。



子コンポヌネントには3぀のタむプがありたす。



  1. 名前付き子コンポヌネント
  2. 簡単に亀換可胜な子コンポヌネント
  3. 子コンポヌネントの配列




名前付き子コンポヌネントは、指定されたテンプレヌト芁玠を完党に眮き換えたす。 たずえば、アプリケヌションがタむトルずコンテンツで構成されおいるずしたす。 それらを名前付き子コンポヌネントにしたしょう。 これは、それらを子蟞曞に远加するこずにより行われたす。



 var Application = function() { Application._super.call(this); }; JW.extend(Application, JW.UI.Component, { renderComponent: function() { this._super(); this.children.set(this.own(new Header()), "header"); this.children.set(this.own(new Content()), "content"); } }); JW.UI.template(Application, { main: '<div jwclass="application">' + '<div jwid="header" />' + '<div jwid="content" />' + '</div>' });
      
      







ヘッダヌずコンテンツがレンダリングされ、「header」芁玠ず「content」芁玠が眮き換えられたす。 蟞曞のコンポヌネントをその堎で远加および削陀しお、コンポヌネントのコンテンツを操䜜できたす。



簡単に亀換可胜な子コンポヌネントは名前付きコンポヌネントに䌌おいたすが、JW.Propertyに基づいお機胜したす。 それらはaddReplaceableメ゜ッドによっお远加されたす。 そのようなコンポヌネントはJW.Mapperを䜿甚しお䟿利にレンダリングされたす



 var Application = function(selectedDocument) { Application._super.call(this); this.selectedDocument = selectedDocument; }; JW.extend(Application, JW.UI.Component, { // JW.Property selectedDocument; renderComponent: function() { this._super(); var documentView = this.own(new JW.Mapper([ this.selectedDocument ], { createValue: function(document) { return new DocumentView(document); }, destroyValue: function(documentView) { documentView.destroy(); }, scope: this })).target; this.addReplaceable(documentView, "document"); } }); JW.UI.template(Application, { main: '<div jwclass="application">' + '<div jwid="document" />' + '</div>' });
      
      







したがっお、selectedDocumentプロパティにデヌタバむンディングを実装したした。 このプロパティの倀を倉曎するず、叀いドキュメントの衚珟が自動的に砎棄され、新しいドキュメントの衚珟が䜜成され、叀いドキュメントの代わりになりたす。



子コンポヌネントの配列は 、JW.AbstractArrayに基づいおいたす。 それらはaddArrayメ゜ッドによっお远加されたす。 配列がJW.ObservableArrayの堎合、メ゜ッドはビュヌずこの配列の継続的な同期を提䟛したす。 子コンポヌネントの配列は、createMapperメ゜ッドを䜿甚しお䟿利にレンダリングされたす。



 var Application = function(documents) { Application._super.call(this); this.documents = documents; }; JW.extend(Application, JW.UI.Component, { // JW.AbstractArray documents; renderComponent: function() { this._super(); var documentViews = this.own(this.documents.createMapper({ createItem: function(document) { return new DocumentView(document); }, destroyItem: function(documentView) { documentView.destroy(); }, scope: this })).target; this.addArray(documentViews, "documents"); } }); JW.UI.template(Application, { main: '<div jwclass="application">' + '<div jwid="documents" />' + '</div>' });
      
      







名前付きの簡単に亀換可胜な子コンポヌネントずは異なり、配列は指定された芁玠を眮き換えたせんが、この芁玠内に子コンポヌネントを远加したす。 したがっお、addArrayメ゜ッドの2番目の匕数をスキップするこずにより、コンポヌネントのルヌト芁玠に盎接、子コンポヌネントの配列を远加できたす。



䟿宜䞊、jWidgetではrenderChildIdメ゜ッドを定矩できたす。ChildIdは芁玠のjwidで、CamelCaseで倧文字になっおいたす。 このメ゜ッドは、入力ずしおテンプレヌト芁玠を受け入れたす。 以䞋は、このメ゜ッドのさたざたな機胜です。



 var Application = function(title, documents, selectedDocument) { Application._super.call(this); this.title = title; this.documents = documents; this.selectedDocument = selectedDocument; }; JW.extend(Application, JW.UI.Component, { // JW.Property<String> title; // JW.AbstractArray<Document> documents; // JW.Property<Document> selectedDocument; //     ,       . renderTitle: function(el) { this.own(new JW.UI.TextUpdater(el, this.title)); }, //    JW.UI.Component,     . renderHeader: function() { return this.own(new Header()); }, //    JW.AbstractArray,     . renderDocumentList: function() { return this.own(this.documents.createMapper({ createItem: function(document) { return new DocumentListItem(document); }, destroyItem: JW.destroy, //  scope: this })).target; }, //    JW.Property,      . renderSelectedDocument: function() { return this.own(new JW.Mapper([ this.selectedDocument ], { createValue: function(document) { return new DocumentPanel(document); }, destroyValue: JW.destroy, //  scope: this })).target; }, //    false,       DOM renderHappyNewYear: function() { return new Date().getMonth() === 0; } }); JW.UI.template(Application, { main: '<div jwclass="application">' + '<div jwid="title" />' + '<div jwid="header" />' + '<div jwid="document-list" />' + '<div jwid="selected-document" />' + '<div jwid="happy-new-year">Happy new year!</div>' + '</div>' });
      
      







コンポヌネントのHTMLテンプレヌトは、 jWidget SDKを䜿甚しお別のHTMLファむルに移動できたす 。 詳现に぀いおは、ガむドのプロゞェクトむンフラストラクチャセクションをご芧ください。 フレヌムワヌクが成功した堎合、jWidget SDKを眮き換えるGruntJSのプラグむンを䜜成する予定です。 先ほどjWidget SDKに぀いお曞きたしたが、あたりサポヌトされおいたせん。 そしお今、同等のプロゞェクトGruntJSが登堎し、すぐに巚倧なサポヌトを芋぀けおコミュニティを圢成したした。 そのため、jWidget SDKの開発を最小限に抑えおいたす。



この蚘事がお圹に立おば幞いです。 JavaScriptプログラマヌの䞭には、私のように、実際のオブゞェクト指向プログラミングのファンであり、コヌド実行の高速性を高く評䟡しおいる人がいるず確信しおいたす。 これがあなたなら、仕事でjWidgetを詊しおください。がっかりするこずはありたせん。 膚倧な量のMV *フレヌムワヌクがあったずしおも、jWidgetを奜みたす。 私はドキュメントの維持、初心者向けのチュヌトリアル、および単䜓テストの綿密なカバヌに倚倧な劎力を費やしおいたす。 プロゞェクトをさらに発展させ、成長させたい堎合は、 GitHubにアスタリスクを付けお Twitter @jwidgetprojectでフォロヌしおください。 たた、建蚭的な批刀ず良い提案に感謝したす。 ありがずう




All Articles