2013-04-16 1 views
2

Используя этот тестовый код, основанный на моем реальном проекте:knockoutjs, добавить новый элемент в массив ребенка без дополнительного объекта отображения

var test = ko.mapping.fromJS({ id: 1, kids: [{ name: "sue"}] }); 
test.kids.push({ name: "tim" }); 
test.kids.push(ko.mapping.fromJS({ name: "joe" })); 
console.log(test); 
console.log(test.kids()[0]); 
console.log(test.kids()[1]); 
console.log(test.kids()[2]); 
test.kids()[2].__ko_mapping__ = undefined; 
console.log(test.kids()[2]); 

Выход консоли в Firebug показывает:

Object { __ko-mapping__={...}, id=d(), kids=d() } 
Object { name=d() } 
Object { name="tim" } 
Object { __ko-mapping__={...}, name=d() } 
Object { name=d() } 

Мои Цель состоит в том, чтобы добавить элементы в массив kids после первоначального сопоставления данных, и эти элементы выглядят идентичными исходным позициям. Если я просто нажимаю объект непосредственно на массив, свойства не являются наблюдаемыми. Если я нажимаю объект, используя ko.mapping.fromJS, он получает дополнительный объект __ko_mapping__. Я бы предпочел не иметь дополнительный объект, поскольку он не кажется необходимым (оригинальные элементы не имеют его и работают нормально), и я мог бы использовать тот же дизайн в тех местах, где я добавляю 1000 элементов позже.

Установка объекта на undefined, похоже, удаляет дополнительный объект, но, скорее, не создавала его, если это было возможно.

+2

'__ko_mapping__' создается и используется плагином сопоставления для элемента« root »при вызове' ko.mapping.fromJS'. Вы не должны заботиться об этом, и он не настраивается, он добавляется автоматически. Если вы боитесь проблем с памятью, тогда вы должны создать функцию-конструктор для своих элементов и использовать это вместо плагина сопоставления. – nemesv

+0

Я согласен с комментарием выше. __ko_mapping__ предназначен для нокаута для отслеживания того, что было добавлено. когда вы вызываете функцию ko.mapping.toJS(), эти дополнительные свойства будут удалены, что вы должны вызвать, чтобы получить чистый объект, когда вы хотите передать его обратно на сервер.С другой стороны, если вы выполняете итерацию через свойства объекта, и вы обеспокоены тем, что это может вызвать проблемы, вы должны выполнить итерацию и проверить hasOwnProperty, чтобы убедиться, что вы выполняете итерации через собственные свойства объектов. __ko_mapping__ не будет фигурировать в этом. –

+0

Я так думаю, но кажется довольно распространенным явлением, что у них будет более оптимизированный метод для этого. Я просто сопоставляю довольно простой объект, а затем хочу что-то добавить к нему позже ... Позор мне пришлось бы отрываться от библиотеки отображения только для этого или просто «не беспокоиться» о дополнительной памяти (возможно, в 5 раз больше). – eselk

ответ

1

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

Так что для будущих читателей, вот это:

test.kids()[2].__ko_mapping__ = undefined; 

Просто установите ko_mapping к неопределенным, если вы хотите, чтобы избавиться от него.

См. Комментарии и другие ответы относительно того, почему это не является хорошей идеей в целом. Для моих нужд и, возможно, у вас есть то же самое, это хорошая идея.

0

Обычно мне полезно создать прочный прототип для «Дети» и сообщить плагину сопоставления использовать его при сопоставлении исходных данных. Это приведет к тому, что содержимое массива будет идентичным и будет иметь дополнительное преимущество, позволяющее вычислять и наблюдать за каждым ребенком.

http://jsfiddle.net/Z9GF5/

var Kid = function(json){ 
    ko.mapping.fromJS(json, {}, this); 
} 

var mapping = { 
    'kids': { 
     create: function(options) { 
      return new Kid(options.data); 
     } 
    } 
} 

Теперь, если у вас есть, чтобы добавить элементы просто создать новые дети.

var test = ko.mapping.fromJS({ id: 1, kids: [{ name: "sue"}] }, mapping); 
test.kids.push(new Kid({ name: "tim" })); 
test.kids.push(new Kid({ name: "joe" })); 
console.log(test); 
console.log(test.kids()[0]); 
console.log(test.kids()[1]); 
console.log(test.kids()[2]); 

Firebug затем показывает:

Object {id: function, kids: function, __ko_mapping__: Object} 
Kid {name: function, __ko_mapping__: Object} 
Kid {name: function, __ko_mapping__: Object} 
Kid {name: function, __ko_mapping__: Object}