2017-02-01 6 views
1

バインディングの結果は正常に見えますが、createSubListはシーンの背後で2回連続して呼び出されます。あなたはそれをブラウザのコンソールで見ることができます。どうすればこの問題を回避できますか?ノックアウトforeachバインディングのメソッドが2回連続して呼び出される

<section> 
<!-- ko foreach : list1 --> 
    <div data-bind='text:$data'></div> 

    <!-- ko foreach : $root.createSubList($data) -->  
     <div data-bind='text:$data'></div> 
    <!-- /ko --> 
<!-- /ko --> 
</section> 

function VM(){ 
    var self = this; 
    self.list1 = [1, 2, 3, 4, 5]; 
    self.createSubList = function(index){ 
     // this method gets called twice, why? 
     console.log(index); 
     return ['Sub1']; 
    } 
} 
ko.applyBindings(new VM()) 

https://jsfiddle.net/7eL2ur8o/2/

答えて

1

この問題が発生した多くの理由があるかもしれません。おそらく、この場合、初期値を取得するためにバインディングの作成時に1回評価し、実際にDOMをバインドする2回目に評価します。 KOは変更追跡のためにあり、変化していることを知る方法は、観測可能なプロパティを再評価することです。

なぜにあるのでしょうか。特別な場合は2回発生しますが、KOの未使用バージョンを読み込んでブレークポイントを設定するのが最も簡単です。

しかし、もっと重要な点があります。バインディングで使用するcreate...で始まるメソッド名があります。 imparativeのプログラミングスタイルを使用していることを認識しておいてください。Knockoutのバインディングは、通常宣言型スタイルで使用されます。

別の言い方をすれば、観察可能なプロパティが副作用を起こさないようにして、同じコンテキストで同じ結果を返すようにしてください。ここにあなたのコードの多くのKOスタイルのバージョンがあります:あなたの提案のための

function VM(){ 
 
    var self = this; 
 
    var list1Input = [1, 2, 3, 4, 5]; 
 
    
 
    function createSubList(index){ 
 
     // this method gets called once 
 
     console.log(index); 
 
     return ['Sub1']; 
 
    } 
 
    
 
    self.list1 = list1Input.map(function(i){ 
 
    return { 
 
     label: i, 
 
     subItems: createSubList(i) 
 
    }; 
 
    }); 
 
} 
 

 
ko.applyBindings(new VM())
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script> 
 

 
<section> 
 
<!-- ko foreach : list1 --> 
 
    <div data-bind='text: $data.label'></div> 
 

 
    <!-- ko foreach : subItems -->  
 
     <div data-bind='text: $data'></div> 
 
    <!-- /ko --> 
 
<!-- /ko --> 
 
</section>

+1

感謝。私はこの質問を投稿する前にこれがなぜ起こるのかを追跡しようとしましたが、難しかったです。私はあなたが提案した宣言的なスタイルで行くつもりです! –

関連する問題