Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从子视图模型修改父视图上可观察到的敲除模式_Javascript_Design Patterns_Knockout.js_Design Principles - Fatal编程技术网

Javascript 从子视图模型修改父视图上可观察到的敲除模式

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

我已经设置了父子视图模型对象结构,需要从子视图更新父视图上的可观察对象。我基本上提出了两种模式:

1] 将父属性的引用传递给子属性,并从子属性中更新该属性:

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失去了控制,我的内存也出现了泄漏,这是因为在子对象上引用父对象会导致循环引用。我删除了父引用,并消除了内存泄漏。很好的副作用:我的代码更具可读性:)