Машинопись неправильный контекст этого

голоса
7

Код:

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, но затем машинопись жалуется на «Невозможно преобразовать функцию в (Пользователь: Пользователь) => пустота требует подписи вызова, но функции не хватает одного.»

Задан 07/10/2012 в 09:04
источник пользователем
На других языках...                            


5 ответов

голоса
5

Я не знаком с ко, так что, возможно, есть лучший способ решить переключение контекста, но ваша ошибка компилятора машинопись вызвана «связывает» тип возвращающихся «Function», который несовместим с типом «RemoveUser». Вы должны быть в состоянии решить эту проблему путем литья возвращаемых функций в исходную сигнатуру типа следующим образом:

this.removeUser = <(user: User) => void> this.removeUser.bind(this);
Ответил 07/10/2012 в 18:33
источник пользователем

голоса
2

В качестве альтернативы можно изменить щелчок привязки использовать в JavaScript связывания функцию , чтобы заставить значение thisбыть модель вида: data-bind="click: $root.MyFunc.bind($root)".

Обратите внимание , что $dataи щелчок eventобъекта по- прежнему будет принят в качестве аргументов MyFuncиз Knockout как описано мыши связывания спецификации. Если вам необходимо изменить аргументы которые передаются MyFunc, просто передать их в функцию связывания после $rootпримерно так: .bind($root, param1, param2). С технической точки зрения эти аргументы будут предваряться к аргументам подается от выбивания, давая аргументы [param1, param2, data, event].

Ответил 15/04/2014 в 21:00
источник пользователем

голоса
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, который будет вызывать оригинальный метод с правильным контекстом.

Не то , чтобы $.proxyэто JQuery вызов так JQuery для этого нужно работать.

Ответил 05/11/2012 в 22:30
источник пользователем

голоса
1

Ну, самое простое решение и то, что я обычно делаю с машинописи и нокаута 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);
            }
        }
}
Ответил 08/12/2012 в 19:59
источник пользователем

голоса
0

Я столкнулся с той же проблемой. Для того, чтобы получить правильный контекст вы можете использовать параметры, которые передаются в clickbinding. Clickbinding проходит 2 параметр, т.е. пользователя и событий Jquery клика.

Если взять событие Jquery, и чем использовать функцию ko.contextFor (), вы можете получить правильный контекст.

Ваша функция будет выглядеть примерно так:

removeUser(user: User, clickEvent: any): void {
    var self = ko.contextFor(clickEvent.srcElement).$root;
    self.users.remove(user);
}
Ответил 01/02/2013 в 04:28
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more