关于 javascript:Knockout 嵌套视图模型

Knockout nested view model

我被什么必须是简单的修复所困扰。我正在使用带有嵌套视图模型的 knockout.js,除了我的删除功能无法正常工作之外,一切似乎都很好。它似乎正确绑定,但是当我单击删除时它不会被触发。

为什么要嵌套视图模型?说来话长,但本质上很多东西都需要在一页上!

下面是代码:

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<section class="mini-form-container">
    <form data-bind="submit: repeatGuest.addDate">
        <input type="date" data-bind="value: repeatGuest.previousStay"/>
        <button type="submit" class="button-secondary">Add date</button>
    </form>
     0">
       
            <input data-bind="
value: date" disabled="disabled"  />
            Remove
       
   
</section>

<section>
   
</section>

Javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function RepeatGuest() {
    /// <summary>Child View Model</summary>
    this.dates = ko.observableArray();
    this.previousStay = ko.observable();
}

RepeatGuest.prototype.addDate = function () {
        var self = this.repeatGuest;
        if (self.previousStay()) {
            self.dates.push({
                date: self.previousStay()
            });
        }
    };

RepeatGuest.prototype.removeDate = function (date) {
    this.dates.remove(date);
}

function ViewModel() {
    var self = this;
    self.repeatGuest = new RepeatGuest();
}
ko.applyBindings(new ViewModel());

这是我的小提琴:http://jsfiddle.net/6Px4M/2/

那么为什么我的删除函数没有被触发呢?

可能的附带问题:嵌套视图模型是否是淘汰赛的错误路径,似乎没有太多关于此的信息?


使用这样的嵌套模型的最佳方法之一是使用 with 绑定。你可以这样做:

1
   ...

现在,范围是你的 repeatGuest 并且你可以直接绑定它的属性。

您的 remove 函数的问题与 this 的值以及当时的 $parent 是谁有关。函数以等于当前作用域的 this 值执行。绑定删除函数时,范围是 date 数组中的对象之一。

处理这个问题的典型方法是确保你的函数总是使用正确的 this 值。这可以在绑定中完成(非常丑陋),例如:

1
Remove

更好的选择是将它绑定到视图模型中,在 repeatGuest 构造函数中:

1
this.removeDate = this.removeDate.bind(this);

这允许实现存在于原型上,并使用强制 this 的正确值的package器在每个实例上覆盖它。或者,如果你不把它放在原型上,那么你可以使用 var self = this; 模式并在处理程序中使用 self

http://jsfiddle.net/cNdJj/


绑定不会访问错误原型上的函数。您现在正在绑定到 viewModel,而不是 RepeatGuest 对象。

如果你将它设置为本地函数,它就可以工作:

http://jsfiddle.net/6Px4M/3/

1
2
3
4
5
6
7
function ViewModel() {
    var self = this;
    self.repeatGuest = new RepeatGuest();
    self.removeDate = function (date) {
        self.repeatguest.dates.remove(date);
    }
}