2012-06-16 3 views
2

Я экспериментирую с нокаутом и плагином отображения и задаюсь вопросом, почему это не работает. У меня есть ViewModel, что я хочу, чтобы загрузить с помощью расширения отображениясопоставление нокаутов, вызывающих stackoverflow

function todoListViewModel(data) { 
    ko.mapping.fromJSON(data, { todos: TodoItem.options }, self); 
    ko.mapping.fromJSON(data, { todos: TodoItem.options }, self); 
} 

отображения имеет опцию из который выглядит следующим образом:

var TodoItem = function (options) { 
     var todoItem = ko.mapping.fromJS(options.data); 

     todoItem.remove = function() { 
      alert('remove'); 
     }; 

     return todoItem; 
    }; 
    TodoItem.options = { 
      create: TodoItem 
    }; 

И данные JSON выглядит следующим образом:

{ 
    "id": "0", 
    "todo": "", 
    "todos": [ 
     { 
      "todo": "Kevin", 
      "isDone": true 
     } 
    ] 
} 

Первый вызов сопоставления завершается успешно, но второй вызов завершился неудачно с потоком stackoverflow: («Невозможно RangeError: максимальный размер стека вызовов превышен» в Chrome)

Если я изменю код, чтобы не передавать параметры для отображения, исключение не выбрасывается.

Я также попытался упростить конструктор ToDo к этому

var TodoItem = function (options) { 
    var todoItem = {}; 

    return todoItem; 
}; 

, но я все еще получаю ту же ошибку.

Похоже, я не могу этого сделать, но мне было интересно, почему?

ответ

3

Проблема с этим битом:

TodoItem.options = { 
    create: TodoItem 
}; 

Вы простирающийся TodoItem со свойством «вариантов», что опять содержит TodoItem - поэтому функция TodoItem имеет свойство, которое содержит себя.

TodoItem.options.create == TodoItem 
TodoItem.options.create.options.create == TodoItem 
TodoItem.options.create.options.create.options.create == TodoItem 
... 

Потому что это только ссылка, это не проблема в JavaScript. Но плагин отображения нокаутов, похоже, выполняет какое-либо действие копирования (или что-то такое же действие) в этом объекте-опции, то есть пытается перебрать все его свойства и, таким образом, попадает в бесконечный цикл.

Вы можете легко решить эту проблему с помощью анонимной функции в качестве оболочки:

TodoItem.options = { 
    create: function(options) { 
     return new TodoItem(options); 
    } 
}; 
+1

Не уверен, что кто голосовал это вниз, но это не похоже на работу, я удалил TodoItem.options вообще и заменить К.О. .mapping.fromJSON (данные, {todos: TodoItem.options}, self); с ko.mapping.fromJSON (данные, {todos: {create: TodoItem}}, self); и код работает. благодаря –

Смежные вопросы