フロントエンドテンプレートエンジン

最後の記事では、「自転車」(「ライト」フレームワークのフレームワーク内のローダーとテンプレートエンジン)の説明に専念しました。 運命の意志により、いくつかのプロジェクトでテンプレートエンジンを選択し、スタンドアロンバージョンにすることを余儀なくされた一方で、多くの新機能を充実させました。 これについては、フロントエンドテンプレートエンジンについて説明します。



しかし、あなたの時間を節約するために、最初にこの記事が面白いかもしれない人を指定します(多くの手紙があるので):









このプロジェクトはFlex.Patternsと呼ばれますが、簡単にするために単にパターンと呼びます。 以下は、簡単に自分自身を再現できるいくつかの例です。 前の記事で説明したFlexとは異なり、パターンは設定やタンバリンとのダンスを必要としません-ピックアップして使用します。 パターンは一般的に非常にシンプルで、それが私の主な目標でした。



たとえば、パターン内のテンプレートは単なるHTMLページであり、それ以上のものではありません。 EJSや他の多くのテンプレートエンジンで使用されているような特定の構文はありません。



<ul> <% for(var i=0; i<supplies.length; i++) {%> <li><%= supplies[i] %></li> <% } %> </ul>
      
      







パターンの構文全体は、3つの定義に制限されています。







テンプレートを作成





さて、例を見てみましょう。 ユーザーを認証するポップアップを作成します。 4つのテンプレートが必要です。







以下はポップアップのテンプレートです。



 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Flex.Template</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <link rel="stylesheet" type="text/css" href="pattern.css" /> </head> <body> <div data-style="Popup" id="{{id}}"> <div data-style="Popup.Container"> <div data-style="Popup.Title"> <p data-style="Popup.Title">{{title}}</p> </div> <div data-style="Popup.Content">{{content}}</div> <div data-style="Popup.Bottom"> <p data-style="Popup.Bottom">{{bottom}}</p> </div> </div> </div> </body> </html>
      
      







すでにお気付きのように、これは最も一般的なHTMLファイルです。 HEADには、CSSファイルとJSファイルを含めることができます。これらのファイルはテンプレートに自動的に含まれ、キャッシュされます。



キャッシュはパターンの重要な部分です。 テンプレート(HTML)とリソース(CSSおよびJS)の両方がlocalStorageに保存されます。つまり、テンプレートを再利用すると、すべてのデータがサーバーからではなくクライアントから取得され、レンダリング速度に最も有利に影響します。 さらに、パターン自体がキャッシュの関連性を監視します。パターンがすべてのパターンとそのリソースのHEADERを要求するたびに。 また、何かが変更された場合、パターンは独立してキャッシュを更新し、システム全体を最新の状態に保ちます。 ただし、承認ウィンドウに戻ります。



レイアウトテンプレート(以降、スペースを節約するために、BODYタグのコンテンツのみを引用します)



 <div data-type="Pattern.Login"> <p>Login</p> {{login}} <p>Password</p> {{password}} <div data-type="Pattern.Controls">{{controls}}</div> </div>
      
      







テキストを入力するためのフィールド(この場合、ユーザー名とパスワードになります)



 <p>{{::value}}</p> <div data-type="TextInput.Wrapper"> <div data-type="TextInput.Container"> <input data-type="TextInput" type="{{type}}" value="{{::value}}" name="TestInput"/> </div> </div>
      
      







上記のラベル{{:: value}}を使用して、valueという変数を介してINPUT.valueとP.innerHTMLをリンクしたことに注意してください。 したがって、INPUTにテキストを入力すると、関連する段落に表示されます。 さらに、作成された値変数がモデルに配置されます。



さて、承認ウィンドウに必要な最後のテンプレートはボタンです。



  <a data-type="Buttons.Flat" id="{{id}}">{{title}}</a>
      
      







先に進む前に、予約をしてください。 パターンが本格的なHTMLファイルをテンプレートとして使用するという事実により、使用されるページとは別にそれらを開く機会が与えられ、これにより、スタイルとロジック(ある場合)を迅速にデバッグすることが可能になります。



テンプレートを添付する





テンプレートは、次の2つの方法でページに添付(レンダリング)できます。







どちらを使用するかは、タスクのみに依存します。 たとえば、ページを読み込んだ直後にテンプレートを描画する必要がある場合は、マークアップを介して添付することをお勧めします。 承認テストウィンドウのようなものについて話している場合は、JavaScriptを介した呼び出しがより適切です。 両方の方法を見てみましょう。



JavaScriptレンダリング





getメソッドは、テンプレート-_patterns.get()のレンダリングを担当します。テンプレートは、-renderメソッドを介してマウント(指定されたノードにアタッチ)できるテンプレートクラスのインスタンスを返します。 以下の例を見てください。すべてが明らかになります。



 var id = flex.unique(); _patterns.get({ url : '/patterns/popup/pattern.html', node : document.body, hooks : { id : id, title : 'Test dialog window', content : _patterns.get({ url : '/patterns/patterns/login/pattern.html', hooks : { login : _patterns.get({ url : '/patterns/controls/textinput/pattern.html', hooks : { type: 'text', } }), password: _patterns.get({ url : '/patterns/controls/textinput/pattern.html', hooks : { type: 'password', } }), controls: _patterns.get({ url : '/patterns/buttons/flat/pattern.html', hooks : [{ title: 'login', id: 'login_button' }, { title: 'cancel', id: 'cancel_button' }] }), } }) } }).render();
      
      







最も重要なパラメーターはURLです。ここで、テンプレートの取得先を指定します。 同様に重要なパラメーターはフックです。 テンプレートで、ラベル-{{name}}を通じてコン​​テンツの場所を示したことを思い出してください。 hooksパラメーターでは、そのような各タグのコンテンツを定義します。



_patterns.get()メソッドが取るすべてのパラメーターの完全な説明は、 ここにあります 。 そして、この例の結果はここにあります



しかし、先に進みます。



HMTLマークアップを介したレンダリング





ページを読み込んだ直後に生成されたテンプレートが必要な状況では、PATTERNタグを使用して、テンプレートをマークアップに直接配置できます。



  <pattern src="/patterns/popup/pattern.html" style="display:none;"> <id>0</id> <title>Test dialog window</title> <content src="/patterns/patterns/login/pattern.html"> <login src="/patterns/controls/textinput/pattern.html"> <type>text</type> </login> <password src="/patterns/controls/textinput/pattern.html"> <type>password</type> </password> <controls src="/patterns/buttons/flat/pattern.html"> <id>login_button</id><title>login</title> <id>cancel_button</id><title>cancel</title> </controls> </content> </pattern>
      
      







この場合、同じ名前のタグを使用してフックを識別します。 つまり、以下の2つの構成の意味は同じです。



 <pattern src="/patterns/popup/pattern.html" style="display:none;"> <id>0</id> <title>Test dialog window</title> ... </pattern>
      
      







 _patterns.get({ url : '/patterns/popup/pattern.html', hooks : { id : 0, title : 'Test dialog window', ... } }).render();
      
      







ルートノードに対してのみPATTERNタグを使用し、ネストされたテンプレートがフックコンテンツとして使用されることを示すためにSCRプロパティを追加するだけであることに注意してください。



つまり、次のマークアップは、パターンがSRCで指定されたアドレスでパターンを検出し、「text」の値にtype hookで適用する必要があることを意味します。



 <login src="/patterns/controls/textinput/pattern.html"> <type>text</type> </login>
      
      







ここでは実際の例を見ることができます。 ページのソースを開いて、JavaScript呼び出しがないこと、およびレンダリングに必要なデータを含む元のページレイアウトにPATTERNタグが存在することを確認します。



パターンリピート





非常に頻繁にパターンを繰り返し繰り返す必要があります。 これの最も顕著な例は表です。 作成するには、2つのテンプレートが必要です。



テーブルテンプレート。



 <table data-type="Demo.Table"> <tr> <th>{{titles.column_0}}</th> <th>{{titles.column_1}}</th> <th>{{titles.column_2}}</th> <th>{{titles.column_3}}</th> </tr> {{rows}} </table>
      
      







そして、テーブル内の行パターン。



 <tr> <td>{{column_0}}</td> <td>{{column_1}}</td> <td>{{column_2}}</td> <td>{{column_3}}</td> </tr>
      
      







これらの2つのテンプレートとデータがあれば、テーブルを描画できます。



 var data_source = []; for (var i = 0; i < 100; i += 1) { data_source.push({ column_0: (Math.random() * 1000).toFixed(4), column_1: (Math.random() * 1000).toFixed(4), column_2: (Math.random() * 1000).toFixed(4), column_3: (Math.random() * 1000).toFixed(4), }); } _patterns.get({ url: '/patterns/table/container/pattern.html', node: document.body, hooks: { titles: { column_0: 'Column #0', column_1: 'Column #1', column_2: 'Column #2', column_3: 'Column #3', }, rows: _patterns.get({ url: '/patterns/table/row/pattern.html', hooks: data_source, }) } }).render();
      
      







ここで実際の例を見つけることができます。



したがって、特定のパターンを数回繰り返すには、フック(フック)の値をデータ配列として渡すだけで十分です。 また、お気づきかもしれませんが、HTMLでテンプレートを定義するときにテンプレートを繰り返すために、以前に承認ウィンドウのボタンで示したように、必要な回数だけフック値を繰り返します。



 <controls src="/patterns/buttons/flat/pattern.html"> <id>login_button</id><title>login</title> <id>cancel_button</id><title>cancel</title> </controls>
      
      







また、ヘッダーのフックの名前はポイント{{titles.column_0}}を介して定義されているため、レンダリング関数で値のより意味のある定義を使用できます。 したがって、すべての見出しはtitlesオブジェクトで定義されます。



コントローラーとコールバック関数





本質的に、パターンでは、コントローラーとコールバック関数は同じものです。 唯一の違いは保管場所です。



ご想像のとおり、コールバック関数はテンプレートのレンダリング時に定義されます。



 _patterns.get({ url : 'some_url', callbacks: { //Callback-function definition success: function (results) { var instance = this, dom = results.dom, model = results.model, binds = results.binds, map = results.map, resources = results.resources; ... } }, }).render();
      
      







ただし、コントローラーを作成するには、次のコンテンツのJSファイルを作成する必要があります



 _controller(function (results) { var instance = this, dom = results.dom, model = results.model, binds = results.binds, map = results.map, resources = results.resources; ... });
      
      







次に、テンプレートに添付するだけです。



 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Flex.Template</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <link rel="stylesheet" type="text/css" href="pattern.css" /> <!-- Attach controller of template --> <script type="text/javascript" src="conroller.js"></script> </head> <body> <div data-style="Popup"> <div data-style="Popup.Container"> <div data-style="Popup.Title"> <p data-style="Popup.Title">{{title}}</p> </div> <div data-style="Popup.Content">{{content}}</div> <div data-style="Popup.Bottom"> <p data-style="Popup.Bottom">{{bottom}}</p> </div> </div> </div> </body> </html>
      
      







これでコントローラーの準備は完了です。 これで、テンプレートが描画された後、コントローラー内で定義されているすべてのものが毎回起動されます。



ただし、最も興味深いのは結果オブジェクトであり、コントローラーとコールバック関数の両方に渡されます。



モデルとコミュニケーション





取得する2つの重要なオブジェクトは、モデルとバインドです



 var model = results.model; var binds = results.binds;
      
      







何かがあることを示すために、テーブル行のテンプレートを次のように変更します。



 <tr> <td style="background:{{::background_0}};">{{column_0}}{{::column_0}}</td> <td style="background:{{::background_1}};">{{column_1}}{{::column_1}}</td> <td style="background:{{::background_2}};">{{column_2}}{{::column_2}}</td> <td style="background:{{::background_3}};">{{column_3}}{{::column_3}}</td> </tr>
      
      







ご覧のとおり、いくつかのリンクを追加しました。 まず、各セルのbackgroundプロパティをbackground_n変数にリンクしました。 セル自体の値についても同じことを行い、それらを変数column_nに関連付けました。



これで、コントローラー(またはコールバック関数)で、ノードの関連プロパティにアクセスできます。



 _patterns.get({ ... callbacks : { success: function (results) { (function (model) { var fun = function () { var r = Math.round(19 * Math.random()), c = Math.round(3 * Math.random()); model.__rows__[r]['column_' + c] = (Math.random() * 1000).toFixed(4); model.__rows__[r]['background_' + c] = 'rgb(' + Math.round(255 * Math.random()) + ', ' + Math.round(255 * Math.random()) + ', ' + Math.round(255 * Math.random()) + ')'; setTimeout(fun, Math.ceil(50 * Math.random())); }; fun(); }(results.model)); } } }).render();
      
      







ここでコイルから飛ばされたテーブルを見ることができます。



そのため、モデルオブジェクトには関連する値へのリンクが含まれています。 __rows__プロパティに注意してください。 この__hook__コンストラクトにより、フックのネストレベルが示されます。 データはルートテンプレート(テーブルテンプレート)に含まれておらず、フック行に埋め込まれているため、モデル.__ rows__を介してデータにアクセスできます。 名前の競合に対する予防策として二重下線が導入されています。



覚えている場合は、承認ウィンドウテンプレートでINPUT.valueをP.innerHTMLにリンクしました。 コールバック関数では、値への参照も取得します。



 _patterns.get({ url : '/patterns/popup/pattern.html', node : document.body, hooks : { id : id, title : 'Test dialog window', content : _patterns.get({ url : '/patterns/patterns/login/pattern.html', hooks : { login : _patterns.get({ url : '/patterns/controls/textinput/pattern.html', hooks : { type: 'text', } }), password: _patterns.get({ url : '/patterns/controls/textinput/pattern.html', hooks : { type: 'password', } }), controls: _patterns.get({ url : '/patterns/buttons/flat/pattern.html', hooks : [{ title: 'login', id: 'login_button' }, { title: 'cancel', id: 'cancel_button' }] }), } }) }, callbacks: { success: function (results) { var instance = this, model = results.model; model.__content__.__login__.value = 'this new login'; } }, }).render();
      
      







モデルは整理されていますが、バインドとは何ですか? また、その構造内のバインドはモデルと同じですが、1つの例外があります-「最後に」は値ではなくメソッドです。



 success: function (results) { var instance = this, dom = results.dom, binds = results.binds, id = null; //Add handle id = binds.__content__.__login__.value.addHandle(function (name, value) { var obj = this; }); //Remove handle binds.__content__.__login__.value.removeHandle(id); }
      
      







そして、そのうちの2つ(メソッド)しかありません。







ご想像のとおり、最初はイベントハンドラーをアタッチし、2番目はイベントハンドラーを削除します。 したがって、モデルの一部のプロパティに関数を「ハング」させることができ、このプロパティが変更されるたびにトリガーされます。



DOMとマップ





他の2つの興味深いオブジェクトは、DOMとマップです。



 var dom = results.dom; var map = results.map;
      
      







承認ウィンドウのボタンテンプレートを少し変更して、domオブジェクトの機能を示します。



  <a data-type="Buttons.Flat" id="{{id}}" {{$button}}>{{title}}</a>
      
      







そこで、ボタンノードにリンク{{$ button}}を追加しました。 したがって、このノードを操作するためのメソッドのコレクションを作成するパターンに関連するノードに注目しました。



 success: function (results) { var instance = this, dom = results.dom; dom.listed.__content__.__controls__[0].button.on('click', function () { alert('You cannot login. It\'s just test. Login is "' + model.__content__.__login__.value + '", and password is "' + model.__content__.__password__.value + '"'); }); dom.listed.__content__.__controls__[1].button.on('click', function () { alert('Do not close me, please.'); }); dom.grouped.__content__.__controls__.button.on('click', function () { alert('This is common handle for both buttons'); }); }
      
      







ご覧のとおり、フォームのボタンにイベントハンドラーをアタッチする機会がありました。 すぐに使用できるすべてのメソッドの完全なリストは、 ここにあります 。 独自のメソッドを追加する方法の説明もあります。



ここでは、domオブジェクトに2つのプロパティがあることに注目してください。







最初のプロパティにはグループ化されたメソッドが含まれます。 つまり、フォームに2つのボタンがあるため、たとえばonメソッドにアクセスする(イベントをアタッチする)ときに、イベントを一度に2つのボタンにアタッチします。 個々のボタンにアクセスする必要がある場合は、リストされているプロパティを使用する必要があります。



次に、マップオブジェクトを使用すると、テンプレートまたはそのパーツのコンテキストに検索が制限されるため、ノードをすばやく検索できます。



 success: function (results) { var instance = this, map = results.map, nodes = null; //Will find all P in whole popup nodes = map.__context.select('p'); //Will find all P inside popup in content area nodes = map.content.__context.select('p'); //Will find all P in textbox-control of login nodes = map.content.login.__context.select('p'); }
      
      







つまり、map.content.login .__ context.select( 'p')は、ログインを示すために定義されたテキストフィールドテンプレートに関連するテンプレートの部分内でのみすべての段落を検索します。



マップオブジェクトを使用して、ノードをすばやく検索し、ノードへのリンクを取得できます。



データ交換





最後に、コールバック関数に渡される最後のオブジェクトはリソースです。 すべてがシンプルです-それはデータ交換メカニズムです。 そのため、テンプレートをレンダリングするときに、resourcesプロパティを定義できます。



 _patterns.get({ url : '/patterns/popup/pattern.html', node : document.body, hooks : { id : id, title : 'Test dialog window', content : _patterns.get({ url : '/patterns/login/pattern.html', hooks : { login : _patterns.get({ url : '/patterns/controls/textinput/pattern.html', hooks : { type: 'text', } }), password: _patterns.get({ url : '/patterns/controls/textinput/pattern.html', hooks : { type: 'password', } }), controls: _patterns.get({ url : '/patterns/buttons/flat/pattern.html', hooks : [{ title: 'login', id: 'login_button' }, { title: 'cancel', id: 'cancel_button' }] }), }, }) }, resources: { field1 : 'one', field2 : 'two' }, callbacks: { success: function (results) { var instance = this, resources = results.resources; window.console.log(resources.field1); window.console.log(resources.field2); //Result in console: //one //two } }, }).render();
      
      







例で示すように、コールバック関数に渡されます。 したがって、レンダリングの前後にデータを交換する機会が得られます。



用語または変化するパターン





実際、これはパターンの最も興味深い部分です(もちろん、私の観点から)。ここで提案されているアプローチは少し困惑するかもしれません。 しかし、まず最初に。



したがって、優れたテンプレートは完全に静的であるとは限らず、レンダリングに使用するデータに応じて何らかの形で変更する必要があります。 この目的のためのテンプレートエンジンの大半は、構文​​を組み合わせて使用​​し、ロジックをマークアップに直接挿入します。 これは、たとえば、記事の冒頭で言及したAJSによって行われます。



 <ul> <% for(var i=0; i<supplies.length; i++) {%> <li><%= supplies[i] %></li> <% } %> </ul>
      
      







パターンがこのような問題をどのように解決するかを示すために、認証ウィンドウの例に戻り、テキストフィールドテンプレートを変更して、パスワードに使用される場合に有効な文字がユーザーに表示されるようにします。



 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Flex.Template</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <link rel="stylesheet" type="text/css" href="pattern.css" /> <!--Attach JS file with condition-handle--> <script type="text/javascript" src="conditions.js"></script> </head> <body> <p>{{::value}}</p> <div data-type="TextInput.Wrapper"> <div data-type="TextInput.Container"> <input data-type="TextInput" type="{{type}}" value="{{::value}}" name="TestInput" {{$input}}/> </div> <!--type=password--> <div data-type="TextInput.Info.Icon"></div> <div data-type="TextInput.Info.Popup"> <p>You can use in password only letters, number and _</p> </div> <!--type--> </div> </body> </html>
      
      







ご覧のとおり、次の新しいマークアップを追加しました。



 <!--[condition_name]=[condition_value]--> <div data-type="TextInput.Info.Icon"></div> <div data-type="TextInput.Info.Popup"> <p>You can use in password only letters, number and _</p> </div> <!--[condition_name]-->
      
      







このようにして、HTMLコメントのマークアップの必要な部分をフレーミングすることにより、条件を定義できます。



また、添付のJSファイル(conditions.js)に気づかずにはいられません。 その内容は次のとおりです。



 _conditions({ type: function (data) { return data.type; } });
      
      







ご覧のとおり、マークアップ内の条件の名前に対応する関数(タイプ)が定義されています。



では、更新された承認ウィンドウテンプレートをレンダリングした後はどうなりますか? パターンアクションのロジックは非常に単純です。テキストフィールドテンプレートで条件を発見すると、パターンは(関数名で)型関数を見つけようとします。 この関数を検出すると、パターンはフック値を渡します(関数の引数はデータです)。 この関数が条件で指定されたパスワードを返す場合、マークアップの追加部分がテンプレートに含まれます。



更新されたログインウィンドウの動作例を次に示します。



さらに、テンプレートに添付された別のファイルだけでなく、レンダリング中に条件を決定できます。



 _patterns.get({ url : '/patterns/popup/pattern.html', node : document.body, hooks : { id : id, title : 'Test dialog window', content : _patterns.get({ url : '/patterns/login/pattern.html', hooks : { login : _patterns.get({ url : '/patterns/controls/textinput/pattern.html', hooks : { type: 'text', }, conditions : { type: function (data) { return data.type; } }, }), password: _patterns.get({ url : '/patterns/controls/textinput/pattern.html', hooks : { type: 'password', }, conditions : { type: function (data) { return data.type; } }, }), controls: _patterns.get({ url : '/patterns/buttons/flat/pattern.html', hooks : [{ title: 'login', id: 'login_button' }, { title: 'cancel', id: 'cancel_button' }] }), }, }) }, }).render();
      
      







おそらく今お話したいのは、テンプレート内の条件が何らかの形でお尻を介して実装されていることです。 急がないでください。 2つの重大な動機があります。







「二番目に」をよりよく理解するために、テーブルの行パターンを変更しましょう。



 <tr> <td>{{column_0}}{{::column_0}}</td> <td>{{column_1}}{{::column_1}}</td> <td>{{column_2}}{{::column_2}}</td> <td> <div> <p>{{column_3}}{{::column_3}}</p> <!--value_sets=0--> <!--sub_value_sets=0--> <p>This value is less than 111</p> <!--sub_value_sets--> <!--sub_value_sets=0.5--> <p>This value is more than 111 and less than 222</p> <!--sub_value_sets--> <!--sub_value_sets=1--> <p>This value is more than 222 and less than 333</p> <!--sub_value_sets--> <!--value_sets--> <!--value_sets=0.5--> <p>This value is more than 333 and less than 666</p> <!--value_sets--> <!--value_sets=1--> <p>This value is more than 666 and less than 1000</p> <!--value_sets--> </div> </td> </tr>
      
      







すべてがトリッキーに見えますよね? しかし、機能条件を見ると、すべてが明らかになります。



 var conditions = { value_sets: function (data) { if (data.column_3 <= 333 ) { return '0'; } if (data.column_3 > 333 && data.column_3 <= 666 ) { return '0.5'; } if (data.column_3 > 666 ) { return '1'; } }, sub_value_sets: function (data) { if (data.column_3 <= 111 ) { return '0'; } if (data.column_3 > 111 && data.column_3 <= 222 ) { return '0.5'; } if (data.column_3 > 222 ) { return '1'; } }, }; conditions.value_sets. tracking = ['column_3']; conditions.sub_value_sets. tracking = ['column_0']; _conditions(conditions);
      
      







実際、すべては単純です。各行の4番目のセルに分類される番号に応じて、この行の署名も変わります。



トラッキングプロパティを通じて、テンプレートを更新するために必要なデータを変更するときにパターンを表示します。この場合、条件を各行の最初と最後のセルの値に関連付けました。



ダイナミクスを追加してレンダリングを実行しましょう。



 var data_source = []; for (var i = 0; i < 100; i += 1) { data_source.push({ column_0: (Math.random() * 1000).toFixed(4), column_1: (Math.random() * 1000).toFixed(4), column_2: (Math.random() * 1000).toFixed(4), column_3: (Math.random() * 1000).toFixed(4), }); } _patterns.get({ url : '/patterns/table/container/pattern.html', node : document.body, hooks : { titles : { column_0: 'Column #0', column_1: 'Column #1', column_2: 'Column #2', column_3: 'Column #3', }, rows : _patterns.get({ url: '/patterns/table/row_con/pattern.html', hooks: data_source, }) }, callbacks : { success: function (results) { (function (model) { var fun = function () { var r = Math.round(99 * Math.random()), c = Math.round(3 * Math.random()); model.__rows__[r]['column_' + c] = (Math.random() * 1000).toFixed(4); setTimeout(fun, Math.ceil(50 * Math.random())); }; fun(); }(results.model)); } } }).render();
      
      







したがって、ご覧のとおり、50ミリ秒ごとです。セルの値を変更します。また、最初または最後のテンプレートが変更された場合、他の多くのテンプレートエンジンが行うように(完全にではなく)、必要な部分で再描画されます。この不名誉の実例はここで見つけることができます



完了する代わりに





実際、説明できる点はまだたくさんありますが、私はすでにあなたの忍耐の限界をはるかに超えているのではないかと心配しています。



パターンの主な利点は次のとおりです。







しかし、これらは私にとってのみの主な利点です。あなたにとっては、それらは異なっていたり、欠けていたりするかもしれません。



ここでは、パターンに関連するすべての詳細な説明を見つけることができます。



これは github プロジェクトページです。



ご清聴ありがとうございました。



All Articles