2016-06-30 4 views
3

계산 된 관찰 가능 함수에서 관찰 가능 항목의 순서로 인해 업데이트되지 않는 계산 된 관찰 가능 항목이 있습니다. 분기를 클릭하면 리프에 계산 된 관찰 가능 항목이 업데이트되지 않습니다. 이것은 의도 된 것입니까?knockoutjs : 계산 된 사항을 순서대로 관찰 할 수 있습니까?

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

자바 스크립트 :

(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

귀하의 selfs는 뷰 모델의 다른 부분에 관한되어 있습니다. – brianlmerritt

+0

몇 가지 추가 설명. - 배열 중 일부 ('branches','leaves')가 * observable * 배열이 아니어야합니까? - 'isCheckedInternal' var은 관찰 할 수 없으므로 변경하면 계산 된 업데이트가 실행되지 않으므로, 적어도이 repro에는 무엇이 있습니까? - Leaf'isChecked'는 계산 된 readonly *이지만 뷰에는 양방향 바인딩이 있습니까? – Jeroen

+0

여하튼, 뷰 모델을 계산할 때 계산 된 함수는 * once * 실행되어 다른 관측 값이 해당 값에 대해 호출 될 때 모든 종속성을 설정합니다.논리 연산자와 초기 리턴 문이 단락되어 초기 실행이 종속성을 올바르게 설정하지 못할 수 있습니다. 관찰 가능한 getter를 재정렬하십시오 (예 : 계산 함수의 시작 부분에서 간단히 호출하여 로컬 변수에 값을 저장하는 것으로 시작). 문제인지 확인하십시오. – Jeroen

답변

1

산출 된 관측 대상의 순서는 건물 dependencies까지입니다. 에서

이 계산 :

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

(ab는 관측 가정 복귀 중 true 또는 false)

만약 && 운영자가 게으른이기 때문에 다음 b가 (평가되지는 false 반환) 및 KO는 에만 b에 종속성을 생성하지 않습니다.

이것은 좋은 일입니다. b에 대한 변경 사항은이 계산 값에 아무런 영향을 미치지 않으므로 재평가는 자원 낭비가 될 수 있습니다.

a 만약이 가치 b이 가지고 다음 종속성을 만들 것입니다 무엇을 찾아야합니다 그렇게 (이 a에 종속성을 가지고 있기 때문에) KO는 계산 재평가됩니다 true 반환하도록 업데이트됩니다.

당신의 바이올린에 관해서는

는 - 지금까지의 내가 볼 수있는 문제는 분기에 isChecked 관찰이 계산 된 allowLeaves에 어떤 식 으로든 연결되지 않는다는 점이다. 따라서 업데이트되지 않습니다. 이 같은 isCheckedInternalLeaf처럼 당신에게 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에 확인 결합 후 예상대로 작동하도록 나타납니다. 당신이 테스트를 할 경우 self.allowBranch이 정의되지 않도록

나는, 노력하고 있습니다 fiddle ...

관련 문제