Knockout.JSの非同期パターン

Knockout.JSは、複雑なWebアプリケーションを作成するための優れたライブラリです。 長い間、テンプレートの非同期メカニズムに欠けていました。 window.setTimeoutが現在のコンテキストが終了する前にコールバックを呼び出すことが判明するまで、実装できませんでした。 つまり コード内
setTimeout("console.log(window.Value)",0),(function (){while (Math.random() < 0.9999999);window.Value = 1;})()
      
      



コンソールへの出力は、1に非常に近い数をランダムに検索する長い機能が完了した後にのみ発生します。

バインディングメカニズムに精通しており、customBindingsを作成できるknockout.jsの記事。



したがって、 setTimeout(コールバック、0)の動作を知っていれば、実装は非常に簡単です。

カスタムバインディングコード:



 ko.bindingHandlers['asynctemplate'] = { update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { $(element).empty(); var template = ko.utils.unwrapObservable(valueAccessor()); if (!template) return; setTimeout(function() { $.ajax({ url: template }).done(function(result){ var view = $(result).appendTo(element)[0]; ko.applyBindings(bindingContext.$data, view); }); }, 0); } }
      
      







アプリケーション:

 //     <div data-bind="asynctemplate: '/Templates/Controls/Components/Modal.html'"></div> //     <div data-bind="asynctemplate: templatePath"></div> //    with  foreach <div data-bind="asynctemplate: templatePath, with: templateViewModel">!!</div>
      
      







タイムアウトがゼロでない場合、問題が発生します。テンプレートを取得するのに時間がかかる場合、ノックアウトバインディングメカニズムが対応する要素に到達する前に、テンプレートをDOMツリーに挿入できます。 この場合、バインディングは2回行われますが、最後は適切なものではありません。



この問題は別の方法で解決できます。「ロード中...」のようなプラグを最初に配置し、サーバーから応答を受信すると、テンプレート自体がロードされる監視可能なフィールドテンプレートを作成します。 しかし、これによりインターフェイスが点滅します。0.5秒間、負荷が表示されます。



誰かが興味を持っているなら、テンプレートキャッシュを追加し、withとforeachと同時にasynctemplateバインディングのサポートを追加できます。



UPD: xdenserがコメント説明したようにすべてがはるかに単純です。 Knockout.jsのドキュメントには 、より簡単な方法があります:カスタムバインディングにinitを追加します。



 ko.bindingHandlers['asynctemplate'] = { init: function () { return { controlsDescendantBindings: true }; }, update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { $(element).empty(); var template = ko.utils.unwrapObservable(valueAccessor()); if (!template) return; $.ajax({ url: template }).done(function (result) { $(result).appendTo(element); ko.applyBindingsToDescendants(bindingContext, element); }); } }
      
      





+テンプレートをバインドするときのバグを修正しました。初期バージョンでは、バインドは最初の要素でのみ発生しました。




All Articles