Как сопоставить с массивом, исходящим от объекта сервера, с помощью плагина Knockout Mapping и немного вычислить?

чтение этого обмена в stackoverflow под названием «Как сопоставить с массивом, исходящим от объекта сервера, используя плагин Knockout Mapping в шаблонах?» (извините, stackoverflow налагает мне ограничения на количество ссылок в сообщении) Я попытался сыграть, используя ответ (jsFiddle: http://jsfiddle.net/ueGAA/1)

так что упражнение заключалось в том, чтобы сделать задачу из учебника knockoutjs на learn.knockoutjs.com под названием «Загрузка и сохранение данных», но с использованием сопоставления нокаутов.

проблема заключается в том, какое объявление ответа в модели представления, которое мне нравится, здесь перенесено в задачу:

var viewModel = 
{
    tasks : ko.mapping.fromJS(data),
    newTaskText: ko.observable(),
    incompleteTasks: ko.computed(function() {     
           return ko.utils.arrayFilter(this.tasks(), function(task) { return !task.isDone() });
    }),
    // Operations
    addTask:  function() {
        alert('Entering add task, count:' + this.tasks().length);
        this.tasks.push(new Task({ title: this.newTaskText() }));
        this.newTaskText("");
    },
    removeTask: function(task) { this.tasks.remove(task) }

}

Дело здесь: внутри объявления ko.computed () this ссылается на окно. Действительно нормально. Правильное поведение может быть получено, если я объявлю ko.computed () после переменной vewmodel.

Сюда:

viewModel.incompleteTasks=ko.computed(function() {
    return ko.utils.arrayFilter(viewModel.tasks(), function(task) { return !task.isDone() });
});

Мне это не нравится, потому что он статически ссылается на объект viewModel в анонимной функции.
вопрос в том, как элегантно объявить неполные задачи непосредственно в объявлении модели просмотра? jsFiddle находится здесь http://jsfiddle.net/Yqg8e/

Благодарность


person Nadir    schedule 02.09.2012    source источник


Ответы (1)


Переключитесь с использования литерала объекта на функцию-конструктор для вашей ViewModel.

function ViewModel() {
    var self = this;

    self.tasks = ko.mapping.fromJS(data);
    self.newTaskText = ko.observable();
    self.incompleteTasks = ko.computed(function() {       
        return ko.utils.arrayFilter(self.tasks(), function(task) { 
            return !task.isDone()
        });
    });
    self.addTask = function() {
       alert('Entering add task, count:' + self.tasks().length);
       self.tasks.push(new Task({ title: self.newTaskText() }));
       self.newTaskText("");
    };
    self.removeTask = function(task) { self.tasks.remove(task) }
}

ko.applyBindings(new ViewModel());​

Обратите внимание также на использование var self = this;, которое позволяет получить доступ к контексту this даже во внутренних анонимных функциях.

Этот метод описан в документации Knockout в разделе Computed Observables (перейдите к разделу под названием Управление этим).

Вот обновленная скрипка: http://jsfiddle.net/Yqg8e/1/

person John Earles    schedule 02.09.2012
comment
Хорошо спасибо. Это было целью моего сообщения, я имею в виду объявление литерала объекта ;-) У меня был другой ответ, глядя на код. на самом деле вычисляемый является зависимымObservable, поэтому мы можем передать объект, который должен быть this, в анонимном. viewModel.incompleteTasks=ko.computed(function() { return ko.utils.arrayFilter(this.tasks(), function(task) { return !task.isDone() }); }, viewModel); В конце концов, мне это не нравится, мне нужно привыкнуть к функции конструктора и трюку с самим собой, как вы предлагаете. Спасибо за указатель rtfm ;-) - person Nadir; 03.09.2012