代码:
export class ViewModel {
public users: knockout.koObservableArrayBase;
constructor () {
this.users = ko.observableArray([]);
this.removeUser = this.removeUser.bind(this);//<-- Here compiller shows error
}
removeUser(user: User): void {
this.users.remove(user);
}
}
HTML:
<table>
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
</tr>
</thead>
<tbody data-bind="foreach: users">
<tr>
<td><a href="#" data-bind="click: $root.removeUser">Remove</a></td>
<td data-bind="text: name"></td>
<td data-bind="text: surname"></td>
</tr>
</tbody>
</table>
问题在于removeUser方法。默认情况下,如果我没有绑定上下文,这= = UserToDelete - 而不是viewModel对象。如果我添加到构造函数:this.removeUser = this.removeUser.bind(this); (manually enforce context)
,那么上下文就是这个== viewmodel,但是然后TypeScript抱怨“无法将函数转换为(user:User)=&gt; void需要一个调用签名,但是函数缺少一个“。
答案 0 :(得分:6)
我不熟悉ko所以也许有更好的方法来解决上下文切换,但是你的打字稿编译错误是由'bind'返回类型'Function'引起的,它与'removeUser'的类型不兼容。您应该能够通过将返回的函数转换为原始类型签名来解决此问题,如下所示:
this.removeUser = <(user: User) => void> this.removeUser.bind(this);
答案 1 :(得分:2)
我有同样的问题,这就是为什么我想出了以下基类来解决我的问题
export class ViewModelBase {
private prefix: string = 'On';
public Initialize() {
for (var methodName in this) {
var fn = this[methodName];
var newMethodName = methodName.substr(this.prefix.length);
if (typeof fn === 'function' && methodName.indexOf(this.prefix) == 0 && this[newMethodName] == undefined) {
this[newMethodName] = $.proxy(fn, this);
}
}
}
}
这样做会循环所有类的成员,如果一个方法以On开头,它将创建一个没有On的新方法,它将使用正确的上下文调用原始方法。
不是$.proxy
是一个jquery调用,所以需要jquery才能工作。
答案 2 :(得分:2)
另一种方法是更改点击绑定,以使用JavaScript的 bind 功能强制this
的值作为您的视图模型:{{1 }}
请注意,data-bind="click: $root.MyFunc.bind($root)"
和点击$data
对象仍会作为<{1}}的参数从Knockout传入,如 click binding 所述规格。如果您需要覆盖传递给event
的参数,只需将它们传递到MyFunc
之后的绑定函数中,如下所示:MyFunc
。从技术上讲,这些参数将预先到Knockout提供的参数,并提供参数$root
。
答案 3 :(得分:1)
嗯,最简单的解决方案以及我通常用typescript和knockout js做的事情是我没有在原型上声明从knockout调用的函数,而是在构造函数中。所以,我会这样做:
export class ViewModel {
public users: knockout.koObservableArrayBase;
removeUser:(user: User) => void;
constructor () {
this.users = ko.observableArray([]);
this.removeUser = (user:User) => {
this.users.remove(user);
}
}
}
答案 4 :(得分:1)
我遇到了同样的问题。要获得正确的上下文,您可以使用clickbinding传递的参数。 clickbinding传递2个参数,即用户和点击的jquery事件。
如果您使用jquery事件,而不是使用ko.contextFor()函数,则可以获得正确的上下文。
您的功能类似于:
removeUser(user: User, clickEvent: any): void {
var self = ko.contextFor(clickEvent.srcElement).$root;
self.users.remove(user);
}