javascript 敲除嵌套视图模型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15163354/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Knockout nested view model
提问by Marvin
I'm stuck with what must be a simple fix. I am using knockout.js with nested view models, and all seems fine except that my remove function is not working correctly. It appears to be binding correctly, however it is not fired when I click remove.
我坚持必须是一个简单的修复。我正在使用带有嵌套视图模型的knockout.js,除了我的remove 功能无法正常工作外,一切似乎都很好。它似乎绑定正确,但是当我单击删除时它不会被触发。
Why nested view models? Long story, but essentially a lot of stuff is required to be on one page!
为什么嵌套视图模型?说来话长,但基本上很多东西都需要在一页上!
So here is the code:
所以这里是代码:
HTML
HTML
<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>
<div data-bind="foreach: repeatGuest.dates, visible: repeatGuest.dates().length > 0">
<div>
<input data-bind="value: date" disabled="disabled" />
<a data-bind="click: $parent.removeDate">Remove</a>
</div>
</div>
</section>
<section>
<div data-bind="text: ko.toJSON($data)"></div>
</section>
Javascript
Javascript
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());
And here is my fiddle: http://jsfiddle.net/6Px4M/2/
这是我的小提琴:http: //jsfiddle.net/6Px4M/2/
So why isn't my remove function getting fired?
那么为什么我的删除功能没有被触发?
Possible side question: is nested view models the wrong path to take in knockout, there doesn't seem to much info on this?
可能的附带问题:嵌套视图模型是否是淘汰赛的错误路径,似乎没有太多关于此的信息?
回答by RP Niemeyer
One of the best ways to work with a nested model like this is to use the with
binding. You can do:
使用这样的嵌套模型的最佳方法之一是使用with
绑定。你可以做:
<div data-bind="with: repeatGuest">
...
</div>
Now, the scope is your repeatGuest
and you can bind directly against its properties.
现在,作用域是你的repeatGuest
,你可以直接绑定它的属性。
The issue with your remove
function is related to the value of this
and who $parent
is at that time. Functions are executed with a value of this
that is equal to the current scope. When your remove function is bound, the scope is one of the objects in the date
array.
你的remove
职能的问题与当时的价值this
和谁有关$parent
。函数以this
等于当前作用域的值执行。当您的 remove 函数被绑定时,作用域是date
数组中的对象之一。
The typically way to handle this is to make sure that your function is bound to always use the correct value of this
. This could be done in the binding (very ugly) like:
处理此问题的典型方法是确保您的函数必须始终使用正确的 值this
。这可以在绑定中完成(非常难看),例如:
<a data-bind="click: $parent.repeatGuest.removeDate.bind($parent.repeatGuest)">Remove</a>
A better option is to bind it in the view model, in your RepeatGuest
constructor:
更好的选择是将它绑定在视图模型中,在您的RepeatGuest
构造函数中:
this.removeDate = this.removeDate.bind(this);
This allows the implementation to live on the prototype and overwrites it on each instance with a wrapper that forces the correct value of this
. Alternatively, if you do not put it on the prototype, then you can use the var self = this;
pattern and use self
in the handler.
这允许实现存在于原型上,并在每个实例上使用强制正确值的包装器覆盖它this
。或者,如果你不把它放在原型上,那么你可以使用var self = this;
模式并self
在处理程序中使用。
回答by Ben McCormick
The binding won't access the function on the wrong prototype. You're binding to the viewModel, not to the RepeatGuest object right now.
绑定不会访问错误原型上的函数。您现在绑定到 viewModel,而不是 RepeatGuest 对象。
It works if you set it as a local function:
如果您将其设置为本地函数,它会起作用:
function ViewModel() {
var self = this;
self.repeatGuest = new RepeatGuest();
self.removeDate = function (date) {
self.repeatguest.dates.remove(date);
}
}