Typescript KnockoutJS 点击绑定错误
Typescript KnockoutJS Click binding bug
一起开始使用 Typescript 和 KnockoutJS,我遇到了一个我还无法推理出的错误。
HTML 看起来如下:
<div class="panel panel-body">
<div class="list-group" data-bind="foreach: Items()">
<a href="#" class="list-group-item"
data-bind="text:Name, click: $parent.SetCurrent">
</a>
</div>
</div>
打字稿如下:
/// <reference path="knockout.d.ts"/>
/// <reference path="jquery.d.ts" />
module ViewModels {
export class ItemViewModel {
public Name: KnockoutObservable<string>;
constructor(name: string) {
this.Name = ko.observable(name);
}//constructor
}
export class MainViewModel {
public SelectedItem: KnockoutObservable<ItemViewModel>;
public Items: KnockoutComputed<Array<ItemViewModel>>;
constructor() {
this.SelectedItem = ko.observable<ItemViewModel>();
this.Items = ko.computed({
owner: this,
read: () => {
return this.get_items();
}
});
}
//TODO: replace this with knockout.mapping plugin transforms
private convert_from_model(items_model) {
var arr = new Array<ItemViewModel>();
var owner = this;
items_model.forEach(function (item) {
var d = new ItemViewModel(item.name);
arr.push(d);
});
return arr;
}
private get_items(): Array<ItemViewModel> {
var items = [{ "name": "AAAA" }, { "name": "BBBB" }, { "name": "CCCC" }, { "name": "DDDD" }];
var items_c = this.convert_from_model(items);
return items_c;
}
public SetCurrent(item: ItemViewModel) {
this.SelectedItem(item);
}
}
}
window.onload = () => {
ko.applyBindings(new ViewModels.MainViewModel());
};
问题是在单击事件时设置当前项目。
public SetCurrent(item: ItemViewModel) {
this.SelectedItem(item);
}
click 事件正确调用 SetCurrent,但是 'this' 的类型是 ItemViewModel 而不是 MainViewModel 应该的。我是否漏掉了一些明显的东西?
这里是 VS2013 solution,其中包含重现问题的所有内容。
谢谢
click: $parent.SetCurrent
Knockout 总是调用 this
设置为 current 视图模型的事件处理程序。这个特定的绑定意味着(到 Knockout)"Invoke $parent.SetCurrent
with the current view model as this
".
最简单的解决方法是使用 箭头函数 以始终获得正确的 this
// Change the definition of SetCurrent like so:
public SetCurrent = (item: ItemViewModel) => {
this.SelectedItem(item);
}
原来这是一个常见的绑定错误。
解决方案是强制绑定
<a href="#" class="list-group-item"
data-bind="text:Name, click: $parent.SetCurrent.bind($parent)">
</a>
您需要在 SetCurrent 的闭包中捕获 this
或将 $parent.SetCurrent
绑定到 $parent
。对于前者,Typescript 提供了一种使用 lambda 执行此操作的好方法,但请注意,SetCurrent 将不再定义在 MainViewModel 的原型上:
SetCurrent = (item: ItemViewModel) => {
this.SelectedItem(item);
}
对于后者,将点击绑定更改为$parent.SetCurrent.bind($parent)
一起开始使用 Typescript 和 KnockoutJS,我遇到了一个我还无法推理出的错误。 HTML 看起来如下:
<div class="panel panel-body">
<div class="list-group" data-bind="foreach: Items()">
<a href="#" class="list-group-item"
data-bind="text:Name, click: $parent.SetCurrent">
</a>
</div>
</div>
打字稿如下:
/// <reference path="knockout.d.ts"/>
/// <reference path="jquery.d.ts" />
module ViewModels {
export class ItemViewModel {
public Name: KnockoutObservable<string>;
constructor(name: string) {
this.Name = ko.observable(name);
}//constructor
}
export class MainViewModel {
public SelectedItem: KnockoutObservable<ItemViewModel>;
public Items: KnockoutComputed<Array<ItemViewModel>>;
constructor() {
this.SelectedItem = ko.observable<ItemViewModel>();
this.Items = ko.computed({
owner: this,
read: () => {
return this.get_items();
}
});
}
//TODO: replace this with knockout.mapping plugin transforms
private convert_from_model(items_model) {
var arr = new Array<ItemViewModel>();
var owner = this;
items_model.forEach(function (item) {
var d = new ItemViewModel(item.name);
arr.push(d);
});
return arr;
}
private get_items(): Array<ItemViewModel> {
var items = [{ "name": "AAAA" }, { "name": "BBBB" }, { "name": "CCCC" }, { "name": "DDDD" }];
var items_c = this.convert_from_model(items);
return items_c;
}
public SetCurrent(item: ItemViewModel) {
this.SelectedItem(item);
}
}
}
window.onload = () => {
ko.applyBindings(new ViewModels.MainViewModel());
};
问题是在单击事件时设置当前项目。
public SetCurrent(item: ItemViewModel) {
this.SelectedItem(item);
}
click 事件正确调用 SetCurrent,但是 'this' 的类型是 ItemViewModel 而不是 MainViewModel 应该的。我是否漏掉了一些明显的东西?
这里是 VS2013 solution,其中包含重现问题的所有内容。
谢谢
click: $parent.SetCurrent
Knockout 总是调用 this
设置为 current 视图模型的事件处理程序。这个特定的绑定意味着(到 Knockout)"Invoke $parent.SetCurrent
with the current view model as this
".
最简单的解决方法是使用 箭头函数 以始终获得正确的 this
// Change the definition of SetCurrent like so:
public SetCurrent = (item: ItemViewModel) => {
this.SelectedItem(item);
}
原来这是一个常见的绑定错误。 解决方案是强制绑定
<a href="#" class="list-group-item"
data-bind="text:Name, click: $parent.SetCurrent.bind($parent)">
</a>
您需要在 SetCurrent 的闭包中捕获 this
或将 $parent.SetCurrent
绑定到 $parent
。对于前者,Typescript 提供了一种使用 lambda 执行此操作的好方法,但请注意,SetCurrent 将不再定义在 MainViewModel 的原型上:
SetCurrent = (item: ItemViewModel) => {
this.SelectedItem(item);
}
对于后者,将点击绑定更改为$parent.SetCurrent.bind($parent)