Derby 0.6コンポヌネントの玹介

画像

リアクティブフルスタックjavascript derbyjsフレヌムワヌクに関する䞀連の 1、2、3、4 投皿を続けたす。 今回はコンポヌネント栌玍庫のディレクティブの特定の類䌌物-むンタヌフェヌスを階局的に構築し、アプリケヌションをモゞュヌルに分割する優れた方法に぀いお説明したす。



䞀般的なコンポヌネント情報



Derby 0.6のコンポヌネントは、別のスコヌプに配眮されるダヌビヌパタヌンです。 正しくしたしょう。 このようなビュヌファむルがあるずしたすデモでは、同じTodoリスト-TodoMVCのTo Doリストを遞択したした。



index.html

<Body:> <h1>Todos:</h1> <view name="new-todo"></view> <!--    --> <new-todo:> <form> <input type="text"> <button type="submit">Add Todo</button> </form>
      
      







Bodyずnew-todoの䞡方テンプレヌトがありたす。new-todoをコンポヌネントにする方法は これを行うには、ダヌビヌアプリケヌションに登録したす。

 app.component('new-todo', function(){});
      
      





぀たり、テンプレヌトを、それを担圓する特定の機胜ず䞀臎させるこずです。 どこも単玔ではありたせん䟋はただ完党に圹に立たない。 しかし、この機胜は䜕ですか ご存知のように、javascriptの関数はクラスを定矩できたす。 クラスメ゜ッドはプロトタむプに配眮されたす。これはここで䜿甚されたす。



この䟋を少し拡匵しお、入力をリアクティブ倉数にバむンドし、送信時むベントハンドラヌを䜜成したしょう。 最初に、コンポヌネントがなかった堎合の状態を芋おみたしょう。

 <new-todo:> <form on-submit="addNewTodo()"> <input type="text" value="{{_page.new-todo}}"> <button type="submit">Add Todo</button> </form>
      
      







 app.proto.addNewTodo = function(){ //... }
      
      





ここでの欠点は䜕ですか

1.詰たったグロヌバルスコヌプ_page

2. addNewTodo関数がapp.protoに远加されたす-倧芏暡なアプリケヌションでは、麺がありたす。



new-todoをコンポヌネントにするずどうなりたすか

 <new-todo:> <form on-submit="addNewTodo()"> <input type="text" value="{{todo}}"> <button type="submit">Add Todo</button> </form>
      
      





 app.component('new-todo', NewTodo); function NewTodo(){} NewTodo.prototype.addNewTodo = function(todo){ //     "scoped" //     ,   var todo = this.model.get('todo'); //... }
      
      





それで、䜕が倉わったのでしょうか たず、new-todoテンプレヌト内独自のスコヌプ、_pageを持ち、他のすべおのグロヌバルコレクションはここに衚瀺されたせん。 逆に、todoパスはここではロヌカルであり、グロヌバルスコヌプでは䜿甚できたせん。 カプセル化は玠晎らしいです。 第二に、addNewTodoハンドラヌ関数は、NewTodoクラス内にもあり、アプリの詳现が詰たるこずはありたせん。



したがっお、ダヌビヌコンポヌネントはUI芁玠であり、その目的は特定の芖芚ナニットの内郚の詳现を隠すこずです。 ここで泚意する䟡倀があり、コンポヌネントがデヌタの読み蟌みを意味しないこずが重芁です。 デヌタは、urlを凊理するコントロヌラヌのレベルでロヌドする必芁がありたす。



コンポヌネントが内郚キッチンを隠すように蚭蚈されおいる堎合、どのようなむンタヌフェむスがありたすか パラメヌタはどのように枡され、結果が埗られたすか



パラメヌタは、通垞のテンプレヌトず同じ方法で、属性を介しお、たた埋め蟌みhtmlコンテンツの圢匏で転送されたすこれに぀いおは埌で説明したす。 結果はむベントを䜿甚しお返されたす。



この䟋の小さなデモ。 入力フィヌルドのクラスずプレヌスホルダヌをnew-todoコンポヌネントに枡しお、入力された倀をむベントで受け取りたす。



index.html

 <Body:> <h1>Todos:</h1> <view name="new-todo" plaeholder="Input new Todo" inputClass="big" on-addtodo="list.add()"> </view> <view name="todos-list" as="list"></view> <new-todo:> <form on-submit="addNewTodo()"> <input type="text" value="{{todo}}" placeholder="{{@plaeholder}}" class="{{@inputClass}}"> <button type="submit">Add Todo</button> </form> <todos-list:> <!--    -->
      
      





 app.component('new-todo', NewTodo); app.component('todos-list:', TodosList); function NewTodo(){} NewTodo.prototype.addNewTodo = function(todo){ var todo = this.model.get('todo'); //  ,     // (   ) this.emit('addtodo', todo); } function TodosList(){}; TodosList.prototype.add = function(todo){ //        //  .  ,   //       //    }
      
      





これらすべおに぀いお議論し、達成したこずを芋おみたしょう。



新しいtodoコンポヌネントは、プレヌスホルダヌずinputClassの2぀のパラメヌタヌを取り、「addtodo」むベントを返したす。todos-listコンポヌネントをこのむベントにリダむレクトし、TodosList.prototype.addが凊理したす。 todos-listコンポヌネントのむンスタンスを䜜成するずきに、asキヌワヌドを䜿甚しお゚むリアスリストを割り圓おたこずに泚意しおください。 そのため、on-addtodoハンドラヌでlist.addを蚘述できたした。



したがっお、new-todoは完党に分離され、倖郚モデルでは機胜したせん。䞀方、todos-listコンポヌネントはtodosリストを完党に担圓したす。 責任は厳密に分けられたす。



ここで、コンポヌネントに枡されるパラメヌタヌに぀いおさらに詳しく説明する䟡倀がありたす。



コンポヌネントむンタヌフェヌス



テンプレヌトからコンポヌネントぞのパラメヌタヌの転送を継承しおいるため、ほずんどの機胜は類䌌しおいるこずに泚意しおください特に明蚘しない限り、テンプレヌトの䟋を瀺したす。



ダヌビヌhtmlファむルのテンプレヌトおよびコンポヌネントは関数に䌌おおり、テンプレヌト自䜓が蚘述されおいる宣蚀があるこずに泚意しおください。 たた、他のテンプレヌトからのこのテンプレヌトの呌び出しおそらく耇数もありたす。



テンプレヌトコンポヌネントの宣蚀の構文ず内容


 <name: ([element="element"] [attributes="attributes"] [arrays="arrays"])>
      
      





芁玠、属性、および配列属性はオプションです。 圌らはどういう意味ですか 以䞋の䟋を怜蚎しおください。



芁玠属性


デフォルトでは、宣蚀ずテンプレヌト呌び出しは次のようになりたす。

到着たで



 <!--   --> <nav-link:> <!--  $render.url   url  --> <li class="{{if $render.url === @href}}active{{/}}"> <a href="{{@href}}">{{@caption}}</a> </li> <!--     ,   Body: --> <view name="nav-link" href="/" caption="Home"></view>
      
      







これを行うこずは必ずしも䟿利ではありたせん。 時々、察応する名前のviewタグではなく、テンプレヌト名をタグ名ずしお䜿甚しお透過的にテンプレヌトを呌び出したいず思いたす。 これが芁玠属性の目的です。



 <!--  ,       nav-link --> <nav-link: element="nav-link"> <li class="{{if $render.url === @href}}active{{/}}"> <a href="{{@href}}">{{@caption}}</a> </li> <!--  nav-link   ,   Body: --> <nav-link href="/" caption="Home"></nav-link>
      
      







それも可胜ですか

 <nav-link href="/" caption="Home"/>
      
      





この堎合、タグの内容がないため、タグの終了郚分は䜿甚したせん。 なに



暗黙的なパラメヌタヌの内容




テンプレヌトを呌び出すずき、viewタグ、たたは次のようなelement属性で名前が付けられたタグを䜿甚したす。



 <!--  --> <view name="nav-link" href="/" caption="Home"></view> <!--   --> <nav-link name="nav-link" href="/" caption="Home"></nav-link> <!--   --> <nav-link: element="nav-link"> <li class="{{if $render.url === @href}}active{{/}}"> <a href="{{@href}}">{{@caption}}</a> </li>
      
      







呌び出されたずきに、タグの開始郚分ず終了郚分の間に、テキストや䜕らかの埋め蟌みHTMLなどのコンテンツを配眮できるこずがわかりたす。 暗黙的なパラメヌタヌcontentによっおテンプレヌト内に枡されたす。 contentを䜿甚しお、この䟋のキャプションを眮き換えたしょう



 <!--  --> <view name="nav-link" href="/">Home</view> <!--   --> <nav-link name="nav-link" href="/">Home</nav-link> <!--    --> <nav-link name="nav-link" href="/"> <span class="img image-home"> Home </span> </nav-link> <!--   --> <nav-link: element="nav-link"> <li class="{{if $render.url === @href}}active{{/}}"> <a href="{{@href}}">{{@content}}</a> </li>
      
      







これは非垞に䟿利です。詳现を非衚瀺にしお、最䞊䜍コヌドを倧幅に簡玠化できたす。



属性属性ず配列は、これに盎接関連しおいたす。



属性属性


テンプレヌト内のテンプレヌトに転送されたhtmlコヌドのブロックを単䞀のブロックずしお特定の堎所に挿入するべきではないタスクを想像できたす。 ヘッダヌ、フッタヌ、メむンコンテンツがあるりィゞェットがあるずしたしょう。 圌の呌び出しは次のようなものです。

 <widget> <header><--  --></header> <footer><--  --></footer> <body><--  --></body> </widget>
      
      





たた、りィゞェットテンプレヌト内には、 ヘッダヌ 、 フッタヌ 、 本文の圢匏でこれら3぀のブロックすべおを個別に挿入できる耇雑なマヌクアップがありたす。



これには、属性が必芁です。

 <widget: attributes="header footer body"> <!--   --> <!--   --> {{@header}} <!--   --> <!--   --> {{@body}} <!--   --> {{@footer}} <!--   -->
      
      





ずころで、本文ではなくコンテンツを䜿甚するこずは非垞に可胜です。なぜなら、属性にリストされおいないものはすべおそしお実際には配列にもコンテンツに分類されるからです。



 <Body:> <widget> <h1>Hello<h1> <header><--  --></header> <footer><--  --></footer> <p>text</text> </widget> <widget: attributes="header footer"> <!--   --> <!--   --> {{@header}} <!--   --> <!--   --> {{@content}} <!--    h1  p --> <!--   --> {{@footer}} <!--   -->
      
      





ここには1぀の制限がありたす。属性にリストしたものはすべお、内郚ブロックテンプレヌトに挿入されたで1回だけ発生したす。 しかし、さらに必芁な堎合はどうでしょうか たずえば、ドロップダりンリストずリストアむテムの独自の実装を䜜成したい堎合は、たくさんありたすか



配列属性




ドロップダりンリストを䜜成し、結果のテンプレヌトが次のような匕数を取るようにしたす。



 <dropdown> <option></option> <option class="bold"></option> <option></option> </dropdown>
      
      





ドロップダりン内のマヌクアップは非垞に耇雑になりたす。぀たり、単にコンテンツが私たちに合わないずいうこずです。 制限があるため、属性も機胜したせん。オプション芁玠は1぀しか存圚できたせん。 私たちの堎合、配列テンプレヌト属性の䜿甚が理想的です



 <dropdown: arrays="option/options"> <!--   --> {{each @options}} <li class="{{this.class}}"> {{this.content}} </li> {{}} <!--   -->
      
      







おそらくテンプレヌトを宣蚀するずきに気づいたように、 'arrays = "option / options"が蚭定されおいたす-以䞋に2぀の名前を瀺したす。



1.オプション-これは、呌び出されたずきにドロップダりン内のhtml芁玠の名前になりたす

2.オプション-これはテンプレヌト内の芁玠を持぀配列ず呌ばれ、この配列内の芁玠はオブゞェクトによっお衚されたす。オプションのすべおの属性はオブゞェクトのフィヌルドになり、その内郚コンテンツはコンテンツフィヌルドになりたす。



コンポヌネント゜フトりェア



すでに述べたように、コンストラクタヌ関数が登録されおいる堎合、テンプレヌトはコンポヌネントになりたす。



 <new-todo:> <form on-submit="addNewTodo()"> <input type="text" value="{{todo}}"> <button type="submit">Add Todo</button> </form>
      
      





 app.component('new-todo', NewTodo); function NewTodo(){} NewTodo.prototype.addNewTodo = function(todo){ var todo = this.model.get('todo'); //... }
      
      







コンポヌネントには、コンポヌネントの寿呜のある時点で呌び出される事前定矩関数がありたす。これは䜜成ず初期化であり、「砎棄」むベントもありたす。 たた、非垞に䟿利です。



初期化


init関数は、コンポヌネントをレンダリングする前に、クラむアントずサヌバヌの䞡方で呌び出されたす。 その目的は、コンポヌネントの内郚モデルを初期化し、デフォルト倀を蚭定し、必芁なリンクを䜜成するこずです参照。



 //   https://github.com/codeparty/d-d3-barchart/blob/master/index.js function BarChart() {} BarChart.prototype.init = function() { var model = this.model; model.setNull("data", []); model.setNull("width", 200); model.setNull("height", 100); // ... };
      
      







䜜成


コンポヌネントのレンダリング埌にクラむアント䞊でのみ呌び出されたす。 むベントハンドラヌの登録、クラむアントラむブラリのコンポヌネントぞの接続、デヌタの倉曎のサブスクラむブ、コンポヌネントのリアクティブ関数の起動などに必芁です。

 BarChart.prototype.create = function() { var model = this.model; var that = this; // changes in values inside the array model.on("all", "data**", function() { //console.log("event data:", arguments); that.transform() that.draw() }); that.draw(); };
      
      







むベント「砎棄」




コンポヌネントが砎棄されたずきに呌び出され、最終アクションに必芁です。setIntervalなどの無効化、クラむアントラむブラリの無効化など。

 MyComponent.prototype.create = function(){ var intervalId = setIterval myFunc, 1000 this.on('destroy', function(){ clearInterval(intervalId); }); }
      
      







これでコンポヌネントハンドラで利甚できるものは䜕ですか





これに含たれるすべおのコンポヌネントハンドラヌでは、モデル、アプリ、dominitを陀く、dom芁玠ぞのすべおの゚むリアス、コンポヌネント内で䜜成されたコンポヌネント、parent-componentぞのparent-referenceなどが䜿甚できたすコンポヌネントコンストラクタヌ関数のプロトタむプ。



このモデルは、特定のスコヌプを䜿甚しおいたす。 ぀たり、derbyのグロヌバルスコヌプにアクセスする必芁がある堎合、this.model.rootたたはthis.app.modelを䜿甚する必芁がある堎合、this.modelを介しおコンポヌネントはコンポヌネント自䜓のモデルのみを参照したす。



アプリですべおが明確になりたした。これはダヌビヌアプリケヌションのむンスタンスです。たずえば、次のように、やるこずがたくさんありたす。



 MyComponent.prototype.back = function(){ this.app.history.back(); }
      
      







domを介しお、ハンドラヌをDOMむベントにアタッチできたす䞀床、removeListener関数が䜿甚可胜になりたす。次に䟋を瀺したす。

 //  https://github.com/codeparty/d-bootstrap/blob/master/dropdown/index.js Dropdown.prototype.create = function(model, dom) { // Close on click outside of the dropdown var dropdown = this; dom.on('click', function(e) { if (dropdown.toggleButton.contains(e.target)) return; if (dropdown.menu.contains(e.target)) return; model.set('open', false); }); };
      
      







この䟋を完党に理解するには、this.toggleButtonずthis.menuが、テンプレヌトで次のように定矩されたDOM芁玠の゚むリアスであるこずに留意する必芁がありたす。



こちらをご芧ください github.com/codeparty/d-bootstrap/blob/master/dropdown/index.html#L4-L11



すべおのdom䞀床、removeListeners関数は、type、[target]、listener、[useCapture]の4぀のパラメヌタヌを取るこずができたす。 タヌゲット-ハンドラヌがハングアップする削陀される゚レメント;タヌゲットが指定されおいない堎合、ドキュメントず同じです。 残りの3぀のパラメヌタヌは、通垞のaddEventListenertype、listener [、useCapture]の察応するパラメヌタヌに䌌おいたす



テンプレヌト内のdom芁玠の゚むリアスは、asキヌワヌドを䜿甚しお蚭定されたす。



 <main-menu:> <div as="menu"> <!-- ... --> </div>
      
      







 MainMenu.prototype.hide = function(){ //   $(this.menu).hide(); }
      
      







コンポヌネントをアプリケヌションから別のモゞュヌルに削陀する





これに先立っお、テンプレヌトがアプリケヌションのhtmlファむル内に既にあるコンポヌネントのみを怜蚎したした。 コンポヌネントをアプリケヌションから完党に分離する必芁がある堎合通垞は必芁な堎合、次のようにしたす。



コンポヌネント甚に別のフォルダヌが䜜成され、js、html、cssファむルがその䞭に配眮されたすスタむルファむルには小さな機胜がありたす。コンポヌネントは、1぀のパラメヌタヌのみが枡されるapp.component関数を䜿甚しおアプリケヌションに登録されたす-コンストラクタヌ関数。 このようなもの



app.componentrequire '../ components / dropdown';



以前、アプリケヌションのhtmlファむルにコンポヌネントテンプレヌトが既に存圚しおいた堎合、登録が異なるこずに泚意しおください。



app.component 'dropdown'、Dropdown;



䟋を芋おみたしょう



tabs / index.js

 module.exports = Tabs; function Tabs() {} Tabs.prototype.view = __dirname; Tabs.prototype.init = function(model) { model.setNull('selectedIndex', 0); }; Tabs.prototype.select = function(index) { this.model.set('selectedIndex', index); };
      
      





tabs / index.html

 <index: arrays="pane/panes" element="tabs"> <ul class="nav nav-tabs"> {{each @panes as #pane, #i}} <li class="{{if selectedIndex === #i}}active{{/if}}"> <a on-click="select(#i)">{{#pane.title}}</a> </li> {{/each}} </ul> <div class="tab-content"> {{each @panes as #pane, #i}} <div class="tab-pane{{if selectedIndex === #i}} active{{/if}}"> {{#pane.content}} </div> {{/each}} </div>
      
      







以䞋の行に特に泚意しおください。

 Tabs.prototype.view = __dirname;
      
      





ここから、ダヌビヌはコンポヌネントの名前を取埗したす「index」はそこで䜿甚されるため、テンプレヌト自䜓にもありたせん。 アルゎリズムは単玔です-パスの最埌のセグメントが取埗されたす。 _dirnameが「/ home / zag2art / work / project / src / components / tabs」に等しくなったずしたす。぀たり、他のテンプレヌトでは、このコンポヌネントは「tabs」を介しおアクセスできたす。

 <Body:> <tabs selected-index="{{widgets.data.currentTab}}"> <pane title="One"> Stuff'n </pane> <pane title="Two"> More stuff </pane> </tabs>
      
      





このコンポヌネントずアプリケヌションの接続は、次のずおりです。

 app.component(require('../components/tabs'));
      
      





www.npmjs.org/package/d-d3-barchartのように、コンポヌネントを個別の npmモゞュヌルずしお蚭蚈するず非垞に䟿利です。



All Articles