2012-05-29 56 views
2

我正在使用KnockoutJS,我想知道一個方法,其中observableArray中的可觀察對象可以通知父變更。這裏有一個例子:如何通知父母的變化

http://jsfiddle.net/paragnair/CEEZ5/

HTML:

<h1 id="heading"> <text data-bind="text:childrenCount"></text> Fields selected</h1> 
<table id="form"> 
<tbody data-bind="foreach:children"> 
    <tr> 
     <td data-bind="text:name"></td> 
     <td><input type="checkbox" data-bind="checked:isSelected"/></td> 
    </tr> 
</tbody> 
</table> 

<a href="#" id="btn-add">Add More Fields</a>​ 

的Javascript:

var Child = function(name) { 
    var self = this; 
    self.name = ko.observable(name); 
    self.isSelected = ko.observable(false); 
}, 
    Parent = function() { 
     var self = this; 
     self.children = ko.observableArray([ 
      new Child('One'), 
      new Child('Two'), 
      new Child('Three') 
      ]); 
     self.children.subscribe(function(children) { 
      header.childrenCount($.map(children, function(a) {     
       return a.isSelected() ? 1 : null; 
      }).length); 
     }); 
    }, 
    header = { 
     childrenCount: ko.observable(0) 
    }; 

var parentModel = new Parent(), 
    extra = parentModel.children().length; 
ko.applyBindings(parentModel, $('#form')[0]); 
ko.applyBindings(header, $('#heading')[0]); 

function setHeading(childrenCount) { 
    header.childrenCount(childrenCount); 
} 

$(document).ready(function() { 
    $('#btn-add').click(function() { 
     extra++; 
     parentModel.children.push(new Child('Extra ' + extra)); 
     return false; 
    }); 
});​ 

在上面的例子中,我要顯示與選定字段數標題。我有一個subscribe事件observableArray,但只有當數組被添加或刪除時觸發,所以當用戶實際檢查字段列表中的複選框時,事件不會被觸發。實現此目的的一種方法是在複選框上添加onchange事件以調用父級方法,該方法inturn調用某個外部方法,該方法更新header對象上的childrenCount。有沒有更好的方法來做到這一點?

回答

6

我認爲你可以用不同的方式來解決這個問題,同時也可以去除不必要的複雜性。您不需要將模型分爲不同的applyBindings調用。事實上,除非絕對必要,否則不建議這樣做,因爲它增加了複雜性,並且如果不小心可能導致雙重綁定。其次,如果你的頭文件是你的parentModels兒童的結果,那麼它確實應該是同一個模型的一部分,當編寫KO模型時,OOP原則可以也應該被應用。這是選擇首先使用KO的優勢。

以下是我將如何解決您的問題。

http://jsfiddle.net/madcapnmckay/edJyp/

var Child = function(name) { 
    var self = this; 
    self.name = ko.observable(name); 
    self.isSelected = ko.observable(false); 
}, 
Parent = function() { 
    var self = this; 
    self.children = ko.observableArray([ 
     new Child('One'), 
     new Child('Two'), 
     new Child('Three') 
     ]); 

    this.childrenCount = ko.computed(function() { 
     var count = 0; 
     ko.utils.arrayForEach(self.children(), function (child) { 
      if (child.isSelected()) { 
       count++; 
      } 
     }); 
     return count; 
    }); 

    this.addMore = function() { 
     self.children.push(new Child("Extra " + (self.children().length + 1))); 
    }; 
}; 

var ViewModel = function() { 
    var self = this; 
    this.parentModel = new Parent(); 
}; 

ko.applyBindings(new ViewModel()); 

注意ViewModel類是多餘的,但我假設你有比這裏顯示了更多的功能,其將被標記到這一點。

順便說一句,爲什麼你覺得你需要在按鈕上使用jquery點擊處理程序?我經常看到這個錯誤,並想知道文檔中的哪些內容會引導您走上這條路?這可以也應該被移到你的viewModel上,這在我的例子中已經完成了。

希望這會有所幫助。

+0

不幸的是,事情是在我的應用程序設計的方式,我必須保持applyBindings分開。所以我需要一種方法來調用一個外部函數,只要一個數組中的一個觀察對象的值被更新。而對於按鈕上的點擊處理程序,這只是一個例子,這不是我的實際項目。 – Wiz