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 メソッドにあります。デフォルトでは、コンテキストをバインドしない場合、これは == UserToDelete - ビューモデル オブジェクトではありません。constructor: に追加するとthis.removeUser = this.removeUser.bind(this); (manually enforce context)、コンテキストは必要に応じて this == ビューモデルになりますが、TypeScript は「関数を (user:User) に変換できません =>void には呼び出し署名が必要ですが、関数には署名がありません」と文句を言います。

4

5 に答える 5

5

私は ko に詳しくないので、コンテキストの切り替えを解決するより良い方法があるかもしれませんが、typescript コンパイラ エラーは、'removeUser' のタイプと互換性のないタイプ 'Function' を返す 'bind' が原因です。次のように、返された関数を元の型シグネチャにキャストすることで、これを解決できるはずです。

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

別の方法として、クリック バインディングを変更して JavaScript のbind関数を使用し、 の値を強制的にthisビュー モデルにすることもできますdata-bind="click: $root.MyFunc.bind($root)"

$dataクリックオブジェクトは、クリック バインディング仕様で説明されているように、Knockout からeventの引数として引き続き渡されることに注意してください。に渡される引数をオーバーライドする必要がある場合は、so: のように bind 関数に渡すだけです。技術的には、これらの引数はKnockout によって提供される引数の前に追加され、arguments が与えられますMyFuncMyFunc$root.bind($root, param1, param2)[param1, param2, data, event]

于 2014-04-15T20:00:35.360 に答える
2

まあ、最も簡単な解決策と私が typescript とノックアウト 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 に答える
1

私は同じ問題に遭遇しました。適切なコンテキストを取得するには、クリックバインディングによって渡されるパラメーターを使用できます。clickbinding は、ユーザーとクリックの jquery イベントの 2 つのパラメーターを渡します。

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 に答える