2016-06-30 14 views
3

私は、計算された観測可能関数内の観測値の順序のために更新されない計算された観測値を持っています。ブランチをクリックしても、葉の計算されたオブザーバブルは更新されません。これは意図されていますか?knockoutjs:計算上の問題はオーダー可能ですか?

https://jsfiddle.net/acL3f1qp/9/

のjavascript:

(function() { 

    function Branch(viewModel) { 
    var self = this; 
    self.isAllowed; 
    self.isChecked = ko.observable(); 
    self.isChecked.subscribe(function(newValue){ 
     //is updating? 
     null; 
    }); 
    self.leaves = []; 
    self.allowLeaves = ko.computed(function() { 
     return viewModel.allowLeaves() && (!self.isAllowed || self.isChecked()); 
    }); 
    } 

    function Leaf(branch) { 
    var self = this; 
    var isCheckedInternal = ko.observable(); 
    self.isAllowed; 
    self.isChecked = ko.computed({ 
      read: function() { 
      return branch.allowLeaves() && isCheckedInternal(); 
      }, 
     write: function(value) { 
      isCheckedInternal(value); 
     } 
    }); 
    } 

    function ViewModel() { 
    var self = this; 
    var branch; 
    var leaf; 
    self.allowLeaves = ko.observable(true); 
    self.branches = []; 
    branch = new Branch(self); 
    branch.isAllowed = true; 
    branch.isChecked(true); 
    leaf = new Leaf(branch); 
    leaf.isAllowed = true; 
    leaf.isChecked(true); 
    branch.leaves.push(leaf); 
    self.branches.push(branch); 
    } 

    ko.applyBindings(new ViewModel()); 

})(); 

HTML:

<div> 
    <label> 
    <input type="checkbox" data-bind="checked: allowLeaves" /> 
    <span>allow leaves</span> 
    </label> 
</div> 
<div class="indent" data-bind="foreach: branches"> 
    <div> 
    <label> 
     <input type="checkbox" data-bind="checked: isChecked, visible: isAllowed" /> 
     <span>branch</span> 
    </label> 
    </div> 
    <div class="indent" data-bind="foreach: leaves"> 
    <div> 
     <label> 
     <input type="checkbox" data-bind="checked: isChecked, visible: isAllowed" /> 
     <span>leaf</span> 
     </label> 
    </div> 
    </div> 
</div> 
<br /> 
clicking on "branch" does 

葉の上に計算された更新しないで!

+0

あなたの自殖は、ビューモデルのさまざまな部分に関連しているしているので、あなたがテストを行う場所self.allowBranchが定義されていません。 – brianlmerritt

+0

追加の備考 - それらの配列のいくつか( 'branches'、' leaves')は* observable *配列ではないはずですか? - 'isCheckedInternal' varは観測できませんので、それを変更すると計算された更新を引き起こすことはありません。だから、少なくともこのreproでは何がポイントですか? - リーフ 'isChecked'は* readonly *で計算されますが、ビューには双方向バインディングがありますか? – Jeroen

+0

いずれにせよ、ビューモデルを構築する際、計算された関数は* once *実行され、他のオブザーバブルがその値に対して呼び出されるときにすべての依存関係が設定されます。論理演算子と早期リターン・ステートメントを短絡するため、最初の実行では依存関係が正しく設定されない可能性があります。観測可能なgetterを並べ替える(例えば、単純に呼び出して、計算された関数の最初にローカル変数に値を保存するなど)、それが問題かどうかを確認してください。 – Jeroen

答えて

1

計算されたオブザーバブルの順番は、建物dependenciesまでです。この計算で

ko.pureComputed(function(){ 
    return a() && b(); 
} 

abが観察され、true又はfalseのいずれかを返すと仮定する)

&&オペレータが怠惰であるので、次にFALSEを返すbは(評価されない場合)とKOはbへの依存を作成しません。aのみに依存します。

これは良いことです - bへの変更はこの計算値に影響を与えないので、再評価することはリソースの無駄になります。

aの場合はtrue KOは(それがaへの依存性を持っているので)、計算を再評価し、そうすることで値bがあり、その後、依存関係が作成されます何かを見つける必要があります返すように更新されます。

あなたのフィドルについては

- 限り私はあなたの問題はブランチ上で観察isCheckedが計算allowLeavesにどのような方法でリンクされていないということがわかります。だから更新されません。あなたはこのようなisCheckedInternalでよりLeafのように見えるようにあなたのBranchの実装を変更した場合

は:

function Branch(viewModel) { 
    var self = this; 
    self.isAllowed = ko.observable(); 
    var isCheckedInternal = ko.observable(); 

    self.leaves = []; 
    self.allowLeaves = ko.pureComputed({ 
    read: function() { 
     return viewModel.allowLeaves() && isCheckedInternal(); 
    }, 
    write: function(val){ 
     isCheckedInternal(val); 
    }}); 
} 

をしてからallowLeavesにチェックを結合し、期待どおりに動作するように見えます。

私が作業しているfiddle ...