1

KO 外部テンプレート エンジンを使用して単一ページの Web アプリケーションを複数のファイルに分割していますが、読み込んでいるテンプレートには KO マークアップしか含まれていません。

このトピックを広範囲に調査したにもかかわらず、読み込まれているテンプレートに KO バインディングを確実に適用する方法がわかりません。

重要なポイントは次のとおりです。

  • テンプレートによって定義された DOM 要素は最初は存在しません
  • 私のテンプレート バインディングは動的なので、ドキュメント全体にバインディングを適用するときに KO がテンプレートを要求することはありません。
  • テンプレートの読み込みを同期させたくない
  • pb は、infuser が、バインディングを 2 回適用していると KO が不平を言う原因となっているテンプレートのキャッシュが発生している可能性があるという事実によって、さらにトリッキーになります。

これは私が持っているコードで、少なくとも 2 つの問題があります。

  • applyBindings を呼び出しているため、テンプレートの読み込みが完了したという保証はありません。
  • KO は、前後に移動するときにバインドを再適用しようとしていると不平を言います

外部テンプレート ノードが DOM に追加されるときにバインディングを 1 回だけ適用するクリーンで信頼性の高い方法についての提案はありますか?

  • index.htmlで:

    <div id="templateDiv" data-bind="template: { name: currentView() }"></div>
    
  • main.js:

    function AdminViewModel() {
         var self = this;
         self.currentView = ko.observable('adminHome');
     }
    
    var viewModel = new AdminViewModel();
    
    var SammyApp = $.sammy('#admin_content', function() {
      //...
      this.get('#/editMembers', function(context) {
          viewModel.currentView('editMembers');
          ko.applyBindings(viewModel, $('.ko-template').get(0));
      });
    };
    
    ko.applyBindings(viewModel);
    
4

4 に答える 4

0

afterRender コールバックを使用して機能するものを思いつきました...少し面倒ですが、改善は歓迎します。

afterRender コールバックは何らかの理由で 2 回呼び出され、2 回目は空のオブジェクトで呼び出されるため、hasOwnProperty('nodeType') のテストが行​​われます。

isBound() は、バインディングが既に要素に適用されているかどうかをチェックします。バインディングの適用後にカスタム マーカー CSS ('ko-applied') クラスを要素に追加しようとしても、確実に機能しませんでした。

koElements 配列のコピーが実際に必要かどうかはわかりませんが、そうしないと、ループ内で未定義の elements[i] が発生してしまうため、afterRender の実行中にテンプレート ローダーが配列を非同期的に更新している可能性があります。

<div id="templateDiv" data-bind="template: { name: currentView(), afterRender: applyTemplateBindings }"></div>

self.applyTemplateBindings = function(koElements) {
            var elements = koElements.slice();
            for (var i = 0, len = elements.length; i < len; i++) {
                var element = elements[i];
                if (element.hasOwnProperty('nodeType') && ! $(element).hasClass('infuser-loading') &&
                    ! isBound(element)) {
                    ko.applyBindings(self, element);
                }
            }
        };

        var isBound = function(node) {
            return !!ko.dataFor(node);
        };
于 2014-06-19T08:23:30.400 に答える
0

I have made a Template engine for KO

https://github.com/AndersMalmgren/Knockout.Bootstrap.TemplateStore/wiki

It requires a Owin enabled web server, once configured it understands that a ViewModel named FooViewModel should be connected to the View called FooView

Install using nuget (For ASP.NET)

Install-Package Knockout.Bootstrap.TemplateStore.SystemWeb

It is also designed to be easy to use in a SPA

Demo https://github.com/AndersMalmgren/Knockout.Bootstrap.Demo

于 2014-06-19T07:19:29.610 に答える