Javascript 从子视图模型修改父视图上可观察到的敲除模式
我已经设置了父子视图模型对象结构,需要从子视图更新父视图上的可观察对象。我基本上提出了两种模式: 1] 将父属性的引用传递给子属性,并从子属性中更新该属性:Javascript 从子视图模型修改父视图上可观察到的敲除模式,javascript,design-patterns,knockout.js,design-principles,Javascript,Design Patterns,Knockout.js,Design Principles,我已经设置了父子视图模型对象结构,需要从子视图更新父视图上的可观察对象。我基本上提出了两种模式: 1] 将父属性的引用传递给子属性,并从子属性中更新该属性: var ParentViewModel = function(){ var self = this; this.selectedItem = ko.observable(); this.child = ko.observable(new ChildViewModel(self.selectedItem)); } v
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] 在父对象上创建子对象的select方法,并引用本地可观察的父对象:
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中以干净且可测试的方式实现此操作,有人有任何其他模式建议吗?还是我或多或少被这两个选项束缚住了?在淘汰中最常见的模式是在你的父母身上放置一个“selectChild”方法,该方法接收一个孩子。在大多数情况下,实际的子对象不需要知道正在选择它 然后在绑定中,您可以绑定到
$root.selectChild
或$parent.selectChild
。传递给绑定到click/event绑定的处理程序的第一个参数是实际数据(在ko2.0中),因此您的方法可以位于父对象上,并将子对象作为第一个参数接收
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>
-
在JSFIDLE中:
你甚至可以进一步简化它。Observable是函数,您传递给它们的第一个参数用于设置它们的值,因此您甚至可以选择不包括selectItem
方法,只需直接绑定$root.selectedItem
(看起来像:)。我通常使用一个单独的方法来显式,给它一个适当的名称(action),以防在设置项之前或之后需要进行额外的处理
在KO 2.0之前(其中引入了
$root
和$parent
以及将数据作为第一个参数传递给单击
和事件
处理程序的更改),我使用了您建议的第一种方法。实际上,您可以做的一件事是不创建子属性(this.parentSelectedItem
),而直接在select
方法中引用parentSelectedItem
(作为参数传递),因为由于创建了闭包,它将在函数中可用。,我很欣赏这个经过深思熟虑的答案。我需要一个+2按钮来回答这个问题。我也会为你加上它:-)非常干净的方式来做这件事。另外,人们想要的子视图模型实际上只是另一个模型(它只是纯数据)。有时候这样想比较容易,不管我们叫他们什么,都是很好的答案。我也遇到了同样的问题,我的viewmodel失去了控制,我的内存也出现了泄漏,这是因为在子对象上引用父对象会导致循环引用。我删除了父引用,并消除了内存泄漏。很好的副作用:我的代码更具可读性:)