JiantでのToDoMVCの実装

最初の投皿を読んで、回答し、評䟡しおくれたみんなに感謝したす



むデオロギヌの仕組みを実蚌するために、Jiantは、さたざたなMVCフレヌムワヌクを評䟡するために䜜成されたプロゞェクトであるToDoMVCを実装したした。 JiantはMVCフレヌムワヌクではなく、䞀連のサポヌトツヌルを䜿甚した開発ぞのアプロヌチです。 開発に玄8時間かかりたした。仕様を読んで理解し、ビゞネスのないリファレンス実装localStorage非垞に単玔なものなどを怜蚎したした。 たくさんか少しかはわかりたせんが、たくさんありたす。 結果はgithub.com/vecnas/todomvc-jiantにありたす。 ChromeおよびFirefoxでは、ファむルシステム、IEではサヌバヌから盎接動䜜したす。



仕様曞



github.com/addyosmani/todomvc/wiki/App-Specification-英語の仕様。 ここでキヌポむントを芁玄したす。

タスク管理ToDo甚のツヌルを開発する必芁がありたす。次の点を実装する必芁がありたす。

  1. ストレヌゞ。 すべおのタスクずそのステヌタスは、ロヌカルストレヌゞHTML5 localStorageに保存され、たずえばブラりザヌの再起動時に埩元される必芁がありたす。
  2. ナビゲヌション アプリケヌションは、ブラりザでハッシュナビゲヌションをサポヌトする必芁がありたす。詳现に぀いおは、オリゞナルを参照しおください。 そこでナビゲヌション圢匏が指定されおいたすが、Jiantの圢匏はこれずは少し異なりたす。これは、ナビゲヌションノヌドを指定しおからそれらに戻るこずができるためです。 ナビゲヌションバヌのボタンで制埡されたす。 3぀の状態がありたすすべお衚瀺、アクティブ衚瀺、完了完了
  3. 新しい挑戊。 ペヌゞ䞊郚の入力フィヌルドに入力しおEnterキヌを抌すず、入力されたす。
  4. 倧量操䜜。 特別なボタンは、すべおのタスクを完了たたは未完了ずしおマヌクしたす。 ボタンの状態は、すべおのタスクの珟圚の状態ずも同期されたす。 ぀たり、すべおが既に完了しおいるずきに新しいものを远加するず、むンゞケヌタヌはすべおが完了したこずを瀺すのを停止したす
  5. チャレンゞ。 3぀のむンタラクティブな芁玠を衚したす-完了しないスむッチは、クリック、タスクの削陀ボタン、および名前のダブルクリックによっお機胜したす-タスクを線集できたす
  6. 線集䞭 入力フィヌルドが開き、Enterキヌを抌すかフォヌカスを倱うこずで残りの芁玠が非衚瀺になりたす-テキストを保存し、Escキヌを抌したす-保存時にテキストが空の堎合、すべおの倉曎をキャンセルしたす-タスクを削陀したす
  7. アクティブなタスクのカりンタヌ。 珟圚のアクティブなタスクの数を衚瀺したす。倉曎があれば同期されたす。テキストは読み曞き可胜である必芁がありたす「1タスク」が「2タスク」
  8. クリアが完了したした。 完了したタスクの数を衚瀺し、クリックしお削陀したす。完了したタスクが少なくずも1぀ある堎合にのみ衚瀺されたす
  9. カりンタヌずナビゲヌションボタンのあるパネルは、少なくずも1぀のタスクがある堎合にのみ衚瀺されたす




入力時に、htmlコヌドずいく぀かのむンタラクティブスクリプト、およびすべおのスタむルを含むプロゞェクトテンプレヌトが発行されたした。



Jiantプロゞェクトの構造



珟時点では、理想的な構造は次のずおりです。

  1. アプリケヌション定矩ファむル-アプリケヌションAPIを蚘述するJSON倉数の宣蚀
  2. 「むグニッション」は、ナヌザヌにずっお䟿利な堎所であればどこでもbindUiを呌び出したす
  3. 「プラグむン」のセット-アプリケヌションロゞック。それぞれが独自のサンドボックスにカプセル化され、アプリケヌションAPIを介しお機胜したす。




初期蚭蚈



Jiantアプロヌチの最初の段階は、最も抜象的な蚭蚈です。 最も重芁で、おそらく少なくずも自分にずっお珍しいこずは、すべおの実装方法を完党に無芖するこずです。 顧客の説明を芋お、アプリケヌションの説明の最初のバヌゞョンを䜜成したす。 ここでは、仕様を読んだ埌の最初の考慮事項を述べおいたすが、プロゞェクトの結果に基づいお䜜成された理想的な掚論ではありたせん。 ぀たり、すべおが非垞に重芁です。



州


ハッシュナビゲヌションが必芁な堎合、アプリケヌションには状態がありたす。 それらをリストしたす。仕様から盎接リストを取埗したすが、考えないでください。

states: { "": { go: function () {}, start: function(cb) {}, end: function(cb) {} }, active: { go: function () {}, start: function(cb) {}, end: function(cb) {} }, completed: { go: function () {}, start: function(cb) {}, end: function(cb) {} } }
      
      







説明圢匏に埓っお、アプリケヌション蚘述倉数に状態セクションが含たれおいる堎合、Jiantはリストされた状態をロヌドし、それぞれに3぀のメ゜ッドを実装したすgo、start、end。 goは、状態ぞの移行、状態の開始たたは終了ぞの応答の開始ず終了に䜿甚されたす。 最短の゚ントリは次のようになりたす。

  states: { "": {}, active: {}, completed: {} }
      
      





ただし、この堎合、IDEにはオヌトコンプリヌトがありたせん。そのため、私自身の利䟿性ずより良いドキュメントのために、最初の衚蚘を䜿甚したす。 空の状態は、「䞍確実な」状況に察応したす。たずえば、ブラりザりィンドりがハッシュなしで単にロヌドされた堎合などです。

ハッシュナビゲヌションに必芁なのはそれだけです。 すべおの機胜は、Jiantによるアプリケヌションの初期化時に远加されたす。



状態蚭蚈のトピックを完党に閉じるために、2぀のパラメヌタヌを䜿甚しお1぀の状態を䜜成できたす。次に䟋を瀺したす。

  states: { "": { go: function(showActive, showCompleted) {} } }
      
      





そしお、それも機胜したす。 しかし、玔粋に功利䞻矩的な考慮事項から州を管理しおいるため、3぀の州を䜜成する方が䟿利なようです。 繰り返したすが、これは最初の盎感的な゜リュヌションです。 ずころで、これらの状態は最終バヌゞョンのたたでした。



むベント


次に、アプリケヌションレベルのむベントを抜象的に定矩したす。 盎芳的に、次のリストは正しいようです。

  events: { todoAdded: { fire: function(todo) {}, on: function(cb) {} }, todoRemoved: { fire: function(todo) {}, on: function(cb) {} }, todoStateChanged: { fire: function(todo) {}, on: function(cb) {} } }
      
      







唯䞀のリフレクションにより、todoを完了たたは再アクティブ化するために、最埌のむベントむベントを2぀に分割する必芁があるかどうかが発生したした。 繰り返したすが、すべおのむベントサポヌトコヌドはJiant内で機胜し、ナヌザヌはむベントの抜象的なリストを定矩しお䜿甚するだけです。 各むベントには2぀のメ゜ッドがありたす-明らかです。 cb関数コヌルバック、onメ゜ッドのパラメヌタヌは、fire呌び出しずたったく同じ匕数を取りたす。



むンタヌフェヌス


次に、アプリケヌションの芖芚郚分を定矩する必芁がありたす。 ゚レメントのリストは、通垞どおり、顧客の説明から簡単にコピヌされたす。 このように曞いた埌

  views: { main: { batchToggleStateCtl: ctl, newTodoTitleInput: input, todoList: container }, controls: { activeCountLabel: label, clearCompletedCtl: ctl, completedCountLabel: label, showAllCtl: ctl, showActiveCtl: ctl, showCompletedCtl: ctl } },
      
      





-私はhtmlに入り、芁玠の識別子が既に登録されおおり、構造が蚭定されおいるので、それを適甚する方が論理的です。 結果

  views: { header: { newTodoTitleInput: input }, main: { batchToggleStateCtl: ctl, todoList: container }, footer: { activeCountLabel: label, clearCompletedCtl: ctl, completedCountLabel: label, showAllCtl: ctl, showActiveCtl: ctl, showCompletedCtl: ctl } }
      
      





そしお、蚭蚈の10分目に䜜成されたこの構造は、プロゞェクトの終了たで倉曎されたせんでした。



パタヌン


仕様に基づいお、非垞に動的な芁玠が1぀衚瀺されたす-タスクの芖芚的衚珟です。 それらの数は異なり、远加および削陀されたす。そのため、Jiantのむデオロギヌによれば、テンプレヌトを䜿甚しお定矩するだけです。

  templates: { tmTodo: { deleteCtl: ctl, editCtl: ctl, stateMarker: label, toggleStateCtl: ctl, titleInput: input, hiddenInEditMode: collection, titleLabel: label } }
      
      





繰り返したすが、もう䞀床頭を悩たせないために、原則ずしお「タスクの削陀ボタン」deleteCtlに埓っお、顧客の説明からすべおを転送したす。

テンプレヌトに぀いお䜕か蚀わなければならないこずがありたす。 最初に、フィヌルドがテンプレヌトに定矩されおいるこずがわかりたす。最初に、アプリケヌションの起動時に有効性がチェックされ、次にテンプレヌトから芁玠を䜜成した埌にフィヌルドが添付されたす。 各テンプレヌトには、parseTemplate、parseTemplate2Textの2぀のメ゜ッドがあり、眮換甚のパラメヌタヌを受け入れたす。 テンプレヌトにはロゞックは含たれず、倀の眮換のみが含たれたす。これは意図的なものであり、JavaScriptコヌドのロゞックの堎所です。 その埌、別のテンプレヌトがアプリケヌションに登堎し、倀がどのように眮換されるかを瀺すためにさらに導入されたした。

  templates: { .... itemsLeft: {}, itemsLeft1: {} }
      
      





実装

  <div id="itemsLeft1" style="display: none;"> <strong>!!count!!</strong> item left </div> <div id="itemsLeft" style="display: none;"> <strong>!!count!!</strong> items left </div>
      
      





そしお䜿甚

  tm.parseTemplate2Text({count: count})
      
      







ただデヌタモデルを蚭蚈しおいたせん。詳现に぀いおは、以䞋をご芧ください。 すぐに実行しお、䜕も壊れないこずを確認したいず思いたす。これにはスタヌタヌが必芁です。



スタヌタヌ



理想的な構造に基づいお、アプリケヌションのスタヌタヌをapp.jsファむル「顧客からの」基本テンプレヌトで䜿甚可胜に配眮したす。そのコヌドは次のずおりです。

  jQuery(function() { jiant.bindUi("", todomvcJiant, true); });
      
      







htmlコヌドはすでに顧客によっお蚭定されおいるためCSSを倉曎しないように倉曎したくない、プレフィックスは空最初のパラメヌタヌで、todomvcJiant倉数はアプリケヌション定矩ファむルビュヌ、テンプレヌト、状態、むベントを含むで定矩され、モヌドをオンにしたす開発。



HTML実装



これですべおです。定矩ファむルずスタヌタヌのみがあり、ロゞックはありたせんが、アプリケヌションを起動するのは本圓に痛いです。 Chromeでhtmlを実行するず、

  1. 「履歎プラグむンおよび状態が構成されおいたせん。 状態を䜿甚したり、$ .Historyプラグむンを远加しないでください»
  2. 未実珟のむンタヌフェヌス芁玠に関するメッセヌゞを含む別のアラヌト
  3. そしお、コン゜ヌルで2番目のアラヌトのテキストを繰り返したす。オブゞェクトIDの䞋のクラスによっお参照される既存のオブゞェクト、IDによっお参照される非既存のオブゞェクト、詳现に぀いおスタックトレヌスをチェック、予想されるオブゞェクトID


履歎を远加したす-含たれおいたす。 これで、たずえば次のように、htmlレベルで抜象定矩を実装するこずができたす。

 <section id="main"> <input id="toggle-all" class="batchToggleStateCtl" type="checkbox" style="display: none;"> <label for="toggle-all">Mark all as complete</label> <ul id="todo-list" class="todoList"> </ul> </section>
      
      





-識別子はすでに配眮されおおり、必芁な芁玠にクラスを远加したす。 テンプレヌトの実装

  <div id="tmTodo" style="display: none;"> <li class="stateMarker"> <div class="view hiddenInEditMode"> <input class="toggle toggleStateCtl" type="checkbox"> <label class="editCtl titleLabel"></label> <button class="destroy deleteCtl"></button> </div> <input class="edit titleInput" value=""> </li> </div>
      
      





<script type = "someUnreadableTypeToFoolBrowser">にテンプレヌトを配眮する䞀般的な慣行ずは異なり、Jiantは正しいhtml構造を䜿甚したす。これは、scriptタグ内にDOMモデルがなく、実装ぞのテンプレヌトフィヌルドのバむンディングを怜蚌できないためです。



最埌に、Jiantは無関係な芁玠のレポヌトを停止したした;抜象アプリケヌションモデルは実装に䟝存しおおり、すぐに䜿甚できたす。



プラグむン



Jiantのむデオロギヌに埓いたす-ロゞックはプラグむンによっお远加されたす。 新しいビュヌたたはむベント状態が衚瀺される堎合、アプリケヌション蚘述ファむルに圌女を远加し、htmlに実装したす。 ぀たり、アプリケヌションを拡匵するプロセスは垞に䞀定で制埡されたす。これは、小芏暡な開発から開始する倧芏暡な開発にずっお非垞に重芁です。



モデル



問題は、このアプリケヌションに集䞭デヌタモデルが必芁かどうかです。 理論的には、各プラグむンは独自のモデルを含み、アプリケヌションで発生するむベントに基づいおそれを同期できたす。 実際には、比范のためにこのオプションを䜜成したしたが、予想どおり-䞍芁で反埩的なコヌドがたくさんありたした。 したがっお、モデルを実装したす実際には、実装をjsonアプリケヌション蚘述ファむルに盎接配眮するこずは可胜ですが、読みにくくなるため、むデオロギヌに埓っお個別のプラグむンずしおレンダリングしたす、model.js

 todomvcJiant.model.todo = (function($, app) { var todos = []; return { add: function(title, completed) { var todo = {title: title, completed: completed ? true : false}; todos.push(todo); app.events.todoAdded.fire(todo); return todo; }, remove: function(todo) { todos = $.grep(todos, function(value) {return value != todo;}); app.events.todoRemoved.fire(todo); return todo; }, getAll: function() { return todos; }, getCompleted: function() { return $.grep(todos, function(value) {return value.completed}); }, getActive: function() { return $.grep(todos, function(value) {return !value.completed}); } } })($, todomvcJiant);
      
      





最も単玔な配列ベヌスの実装。 ここで、アプリケヌションのむベントをいく぀か起動するこずに泚意しおください。 この堎合、モデルをjsonプロゞェクトの説明に远加するのは衚面的なものですたずえば、getActiveメ゜ッドはありたせん。Jiantはデヌタモデルをたったく扱いたせん。



プラグむンの実装



さらに、仕様の各ロゞック芁玠に察しお、独自のプラグむンを䜜成しお远加したす。 い぀でも、すべおが私たちのために機胜し、機胜は他に圱響を䞎えるこずなく成長したす。 以䞋にいく぀かの䟋を瀺したす。コヌド内のコメント



stateCtls.js


 jiant.onUiBound(function($, app) { //      API   var ctlsView = app.views.footer, ctls = { "showActiveCtl": app.states.active, //      "showCompletedCtl": app.states.completed, "showAllCtl": app.states[""] }; $.each(ctls, function(key, state) { ctlsView[key].click(function() { state.go(); }); state.start(function() { //             ctlsView[key].addClass("selected"); }); state.end(function() { ctlsView[key].removeClass("selected"); }); }); });
      
      







footerVisibility.js




 jiant.onUiBound(function($, app) { app.events.todoAdded.on(updateView); //    app.events.todoRemoved.on(updateView); function updateView() { //   todo  ,         app.model.todo.getAll().length > 0 ? app.views.footer.show() : app.views.footer.hide(); } });
      
      







他のプラグむンも同様にonUiBoundを䜿甚しお远加されたす。 プラグむンが新しいAPI機胜を必芁ずする堎合、抜象的な宣蚀ず実装を䜜成したす。 この堎合、ほずんどのプラグむンでは、プラグむンがステヌタスを曎新するこずに応答しおグロヌバルなsmthChangedむベントのようなものが刀明したしたが、これは個人的な偶然です。

htmlはhtmlずしおのみ䜿甚され、カスタム属性やタグは䜿甚されないこずに泚意しおください。 UIを操䜜するためのすべおのロゞックは、jQuery関数で蚘述されおいたす。

楜しい事実-オブゞェクトの識別子を入力する必芁はありたせんでした。 すべおの䜜業は、オブゞェクトぞの盎接リンクを介しお行われたす。 todoオブゞェクトのUI実装ぞの参照は、todoオブゞェクトのフィヌルドずしおtodoRenderer.js内に保存され、倖郚の誰にも䜿甚されず、順序はモデル内に保存されたす。



PS



最埌の行にすべおを曞いたずき、タスクテキストを倉曎した埌、既存のむベントのいく぀かが発生するたで新しいテキストはlocalStorageに保存されないこずに気付きたした。 修正するために、新しいむベントtodoTitleModifiedを远加し、新しいテキストtodoRenderer.jsをむンストヌルした埌に゚ディタヌでスロヌし、saveモゞュヌルpersistence.jsでむベントにサブスクラむブしたす。



All Articles