knockout.js - Typescript konteks salah ini


Kode :

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>

Masalah ada pada metode removeUser. Secara default, jika saya tidak mengikat konteks, this == UserToDelete - bukan objek viewModel. Jika saya menambahkan ke konstruktor: this.removeUser=this.removeUser.bind(this); (memaksa konteks secara manual), maka konteks akan sesuai yang dibutuhkan this == viewmodel, tapi kemudian TypeScript mengeluh untuk "Cannot convert Function to (user:User)=>void requires a call signatures, but Function lacks one."

Jawaban #1

Saya tidak terbiasa dengan ko jadi mungkin ada cara yang lebih baik untuk menyelesaikan pergantian konteks, tetapi kesalahan compiler typescript Anda disebabkan oleh 'bind' yang mengembalikan tipe 'Function' yang tidak kompatibel dengan tipe 'removeUser'. Anda seharusnya dapat menyelesaikan ini dengan mengubah fungsi yang dikembalikan menjadi tanda tangan tipe asli seperti berikut:

this.removeUser = <(user: User) => void> this.removeUser.bind(this);

Jawaban #2

Ya, saya mengalami masalah yang sama itulah mengapa saya membuat kelas dasar berikut untuk memperbaiki masalah saya

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);
            }
        }
    }
}

apa yang dilakukan ini adalah mengulang semua anggota kelas Anda dan jika sebuah metode dimulai dengan On, itu akan membuat metode baru tanpa On yang akan memanggil metode asli dengan konteks yang benar.

Bukan berarti $.proxy adalah panggilan jquery sehingga jquery diperlukan agar ini berfungsi.

Artikel terkait