2017-08-04 54 views
1

把這個代碼:淘汰賽認購不叫改變觀察的數組時

var koEvents = new ko.subscribable(); 
 

 
var viewModel = function() { 
 
    var self = this; 
 

 
    self.data = ko.observableArray([{ 
 
     valid: true 
 
    }, { 
 
     valid: true 
 
    }]); 
 

 
    self.isValid = ko.computed(function() { 
 
     var isValid = true; 
 
     ko.utils.arrayForEach(self.data(), function(item) { 
 
     console.log(item.valid); 
 
     if (!item.valid) { 
 
      isValid = false; 
 
      return; 
 
     }; 
 
     }); 
 
     return isValid; 
 
    }, this).subscribe(function(newValue) { 
 
     alert("Subscribe called!"); 
 
     koEvents.notifySubscribers(newValue, "dataChanged"); 
 
    }.bind(this)); 
 

 
    return { 
 
     data: self.data, 
 
     isValid: self.isValid, 
 
    }; 
 
} 
 

 
var vm = new viewModel(); 
 
ko.applyBindings(vm, document.getElementById("container")); 
 

 
vm.data()[0].valid = false;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<div id="container"> 
 
    <div data-bind="text: isValid ? 'valid': 'invalid'"> 
 
    </div> 
 
</div>

我有兩個問題...

  1. 爲什麼self.isValid不叫,當我做這個vm.data()[0].valid = false;
  2. 爲什麼訂閱(alert("Subscribe called!");)在最初的isValid爲true並且以後設置爲false時未被調用?我期望在我的代碼中調用兩次。

感謝

回答

2

有與該代碼的幾個問題,但相對於你問的主要問題是,在可觀察到的排列變換對象上的不可觀測性(valid)是不改變可觀察數組,只是它內部對象的一個​​屬性。所以自然沒有通知。如果你想要通知,你需要看valid屬性(這意味着它必須是可觀察的)。

其他問題:

  1. 一個與淘汰賽的問題是,它有時解開觀測/ computeds你,但如果他們的表達它的一部分   —你必須這樣做(與()):

    <div data-bind="text: isValid() ? 'valid': 'invalid'"></div> 
    <!-- ------------------------^^       --> 
    

    你的代碼是在試探是否isValid(不是isValid())是truthy。它始終是,因爲它是一個函數參考。

    僅當標識符不是表達式的一部分時,KO纔會爲您自動解包。舉例來說,這個工程:

    <!-- Works --> 
    <div data-bind="visible: isValid">...</div> 
    

    但這並不:

    <!-- Doesn't work --> 
    <div data-bind="visible: !isValid">...</div> 
    

    (當isValid是可觀察/計算)。

  2. 您正在將self.isValid設置爲訂閱句柄,而不是計算的,因爲您已經過度使用了鏈接。 :-)你需要完成通話結束後computed分配,並然後訂閱:

    self.isValid = ko.computed(function() { 
        // ... 
    }, this); // <=== End the assignment here 
    self.isValid.subscribe(function(newValue) { 
        // ... 
    }.bind(this)); 
    
  3. 您使用self = this,但隨後也通過thiscomputed使用bindsubscribe 。這是無害的,但毫無意義。一個或另一個是你需要的。

  4. 不需要創建一個新的獨立對象作爲您的虛擬機構造函數的返回值;你已經有一個對象(由new創建的對象)。

下面是各種變化的例子。該valid財產上的第一項設置爲false 800毫秒後:

var koEvents = new ko.subscribable(); 
 

 
var viewModel = function() { 
 
    this.data = ko.observableArray([{ 
 
     valid: ko.observable(true) 
 
    }, { 
 
     valid: ko.observable(true) 
 
    }]); 
 

 
    this.isValid = ko.computed(function() { 
 
     var isValid = true; 
 
     ko.utils.arrayForEach(this.data(), function(item) { 
 
     console.log(item.valid()); 
 
     if (!item.valid()) { 
 
      isValid = false; 
 
      return; 
 
     }; 
 
     }); 
 
     return isValid; 
 
    }, this); 
 
    this.isValid.subscribe(function(newValue) { 
 
     alert("Subscribe called!"); 
 
     koEvents.notifySubscribers(newValue, "dataChanged"); 
 
    }); 
 
} 
 

 
var vm = new viewModel(); 
 
ko.applyBindings(vm, document.getElementById("container")); 
 

 
setTimeout(function() { 
 
    vm.data()[0].valid(false); 
 
}, 800);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<div id="container"> 
 
    <div data-bind="text: isValid() ? 'valid' : 'invalid'"></div> 
 
</div>

+0

謝謝! ...以及我被告知要使用Stack Snippets而不是Fiddle ...所以通常我會更新小提琴並在「答案」中提供新的小提琴鏈接......但是我看不到我如何更新代碼沒有在這個問題上做? – MojoDK

+0

@MojoDK:你不能。當不可避免的做到這一點時,最好的辦法就是在第一句話「我嘗試做X回答但它仍然不起作用:」或類似的東西時加上第二個片段。 (然後一旦有必要的答案,你可以再次刪除它。)這樣做很重要,以限制它已經存在的問題(問題並不意味着移動目標)。在這種情況下,他們是,所以它會沒事的。很高興幫助! –