我有一个基于递归结构的淘汰视图模型(用typescript编写)。简化版如下:
class ReportGroupViewModel {
constructor(name?: string, subGroups?: ReportGroupViewModel[]) {
this.name = ko.observable(name || '');
this.subGroups = <KnockoutObservableArray<ReportGroupViewModel>>(ko.observableArray(subGroups || []));
}
name: KnockoutObservable<string>;
subGroups: KnockoutObservableArray<ReportGroupViewModel>;
addSubGroup(): void {
this.subGroups.push(new ReportGroupViewModel());
}
deleteSubGroup(subGroup: ReportGroupViewModel): void {
console.log(this.name());
this.subGroups.remove(subGroup);
}
}
在我看来,我使用递归模板列出组。
<ul data-bind="template: { name: 'subGroupTemplate', foreach: subGroups }"></ul>
简化模板如下:
<script id="subGroupTemplate" type="text/html">
<span class="item-actions pull-right">
<span data-bind="click: addSubGroup">Add Sub Group</span>
<span data-bind="click: $parent.deleteSubGroup">Delete Sub Group</span>
</span>
<li>
<input type="text" data-bind="textInput: name" placeholder="Name"/>
</li>
<ul data-bind="template: {name: 'subGroupTemplate', foreach: subGroups }"></ul>
</script>
我遇到的问题是删除绑定不会在父对象上触发,而是在子对象上触发(即它就像绑定是data-bind="click: deleteSubGroup"
一样,没有$parent.
)从登录到JS控制台的名称中可以看到。我在https://jsfiddle.net/po173qqh/3/
我做错了什么导致在层次结构的错误级别调用deleteSubGroup方法?
答案 0 :(得分:1)
输入$parent.deleteSubGroup
即可参考$parent
中的方法。尽管如此,仍然使用$data
作为this
来调用该方法。您必须告诉必须通过绑定将$parent
用作this
:
<span data-bind="click: $parent.deleteSubGroup.bind($parent, $data)">Delete Sub Group</span>
或者,您可以使用var self = this
模式并在方法中使用self
,但我不确定它在Typescript中是如何工作的......
修改:这可能是小提琴打字稿转换,但我必须移除{}
内的applyBindings
来修复它:https://jsfiddle.net/qf66w75p/
编辑2:正如Tsvetomir Nikolov在评论中建议的那样,您还可以使用箭头函数将函数显式绑定到父上下文。绝对是最干净的选择。谢谢,Tsvetomir! https://jsfiddle.net/y9ax95fy/
答案 1 :(得分:0)
如果使用Knockout Punches,则由“Wrapped event callbacks”预处理器自动修复,然后您可以使用现有的绑定和视图模型。解释:
将模型中的函数绑定到事件时,很容易简单地为绑定提供函数引用,例如
click: $parent.removePlace
。但是,当以这种方式绑定时,对$parent
的引用将丢失;将使用默认removePlace
值(当前模型对象)调用this
方法。