2012-04-04 43 views
14

我有一个父子视图模型对象结构的设置,需要更新父对象的可观察对象。我基本上拿出两种模式这样做的:从子视图模型修改父对象的可见性模式

var ParentViewModel = function(){ 
    var self = this; 
    this.selectedItem = ko.observable(); 
    this.child = ko.observable(new ChildViewModel(self.selectedItem)); 
} 

var ChildViewModel = function(parentSelectedItem){ 
    var self = this; 
    this.id = ko.observable(); 
    this.parentSelectedItem = parentSelectedItem; 
    this.select = function(){ 
     self.parentSelectedItem(self); 
    } 
} 

2]制作孩子的:

1]从孩子内通过parent属性给孩子的参考和更新属性在父级上选择方法并参考父级的本地可见性:

var ParentViewModel = function(){ 
    var self = this; 
    this.selectedItem = ko.observable(); 

    var child = new ChildViewModel(); 
    child.select = function(){ 
     self.selectedItem(child); 
    } 
    this.child = ko.observable(child); 
} 

var ChildViewModel = function(){ 
    this.id = ko.observable(); 
} 

这两种模式都不会让我头晕眼花。第一个将整个属性引用推入到子视图模型中,第二个定义了子范围之外的子函数。

有没有人有任何其他模式的建议,如何在javascript中以干净和可测试的方式实现此操作?或者我或多或少地陷入了这两种选择?

回答

19

在Knockout中最常见的模式是在你的父母身上放置一个“selectChild”方法来接受孩子。在大多数情况下,实际的孩子不需要知道它被选中。

然后在您的绑定中,您可以绑定到$root.selectChild$parent.selectChild。传递给绑定到click/event绑定的处理程序的第一个参数是实际数据(在KO 2.0中),因此您的方法可以在父级上生存,并接收子级作为第一个arg。

var Item = function(id, name) { 
    this.id = id; 
    this.name = ko.observable(name);  
}; 

var ViewModel = function() { 
    var self = this; 
    this.items = ko.observableArray([ 
     new Item(1, "one"), 
     new Item(2, "two"), 
     new Item(3, "three") 
    ]); 

    this.selectedItem = ko.observable(); 

    this.selectItem = function(item) { 
     self.selectedItem(item); 
    };  
}; 

在这种情况下,你的绑定看起来像:

<ul data-bind="foreach: items"> 
    <li> 
     <a href="#" data-bind="text: name, click: $root.selectItem"></a> 
    </li> 
</ul> 

这是的jsfiddle:http://jsfiddle.net/rniemeyer/anRsA/

你甚至可以进一步简化它。可观察物是函数,您传递给它们的第一个参数用于设置它们的值,因此您甚至可以选择不包含selectItem方法,并直接与$root.selectedItem直接绑定(看起来像:http://jsfiddle.net/rniemeyer/anRsA/1/)。我通常使用一个单独的方法来明确,给它一个合适的名字(动作),以及在设置项目之前或之后需要进行额外处理的情况。

到KO 2.0(其中$root$parent用变化而引入到数据作为第一个参数传递给clickevent处理程序)在此之前,我曾经使用您建议相当多的第一种方法。你可以在那里做的一件事实际上并不是直接在select方法中创建子属性(this.parentSelectedItem)并且仅仅引用parentSelectedItem(作为参数传递),因为它将在函数中可用,因为创建的闭包。

+0

谢谢瑞恩,我很欣赏经过深思熟虑的答案。 – KodeKreachor 2012-04-04 12:30:19

+0

我需要一个+2按钮来解答这个问题 – KodeKreachor 2012-04-04 14:21:59

+0

我会为你加上:-)非常干净的方式来做到这一点。另外,经常退出人们想要的子视图模型实际上只是另一种模型(它的纯粹数据)。有时候更容易想到这种方式,无论我们称之为 – 2012-04-04 22:00:50

相关问题