8

代码:

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 方法中。默认情况下,如果我不绑定上下文,则 this == UserToDelete - 不是 viewModel 对象。如果我添加到构造函数:this.removeUser = this.removeUser.bind(this); (manually enforce context),那么上下文是需要的 this == viewmodel,但是 TypeScript 抱怨“无法将函数转换为 (user:User)=>void 需要调用签名,但函数缺少调用签名。”

4

5 回答 5

5

我不熟悉 ko 所以也许有更好的方法来解决上下文切换,但是你的打字稿编译器错误是由'bind'返回类型'Function'引起的,它与'removeUser'的类型不兼容。您应该能够通过将返回的函数转换为原始类型签名来解决此问题,如下所示:

this.removeUser = <(user: User) => void> this.removeUser.bind(this);
于 2012-10-07T17:33:28.907 回答
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 才能工作。

于 2012-11-05T21:30:35.177 回答
2

好吧,最简单的解决方案以及我通常对 typescript 和 knockout js 所做的事情是,我不在原型上声明从敲除调用的函数,而是在构造函数中声明。所以,我会这样:

export class ViewModel {
        public users: knockout.koObservableArrayBase;
        removeUser:(user: User) => void;

        constructor () {
            this.users = ko.observableArray([]);
            this.removeUser = (user:User) => {
                this.users.remove(user);
            }
        }
}
于 2012-12-08T18:59:24.677 回答
2

另一种方法是更改​​点击绑定以使用 JavaScript 的绑定函数来强制 的值this成为您的视图模型:data-bind="click: $root.MyFunc.bind($root)"

请注意,$data点击event对象仍将作为MyFunc来自 Knockout 的参数传入,如点击绑定规范所述。如果您需要覆盖传递给的参数MyFunc,只需将它们传递给绑定函数,如下所示$root.bind($root, param1, param2)从技术上讲,这些参数将被添加到由 Knockout 提供的参数之前,给出 arguments [param1, param2, data, event]

于 2014-04-15T20:00:35.360 回答
1

我遇到了同样的问题。要获得正确的上下文,您可以使用点击绑定传递的参数。点击绑定传递2个参数,即点击的用户和jquery事件。

如果您使用 jquery 事件,而不是使用 ko.contextFor() 函数,您可以获得正确的上下文。

你的函数看起来像:

removeUser(user: User, clickEvent: any): void {
    var self = ko.contextFor(clickEvent.srcElement).$root;
    self.users.remove(user);
}
于 2013-02-01T03:28:24.293 回答