这是我的情景。 我使用的是淘汰赛映射插件为我创造一个可观察的视图模型的层次结构。 我的层次结构嵌套在它的元素。 在层次结构中的特定点我想提出的添加按钮,在observablearray插入该元素的一个新的空白副本。 问题是我不能随便说whateverArray.push(新的MyObject())。
由于映射插件实际上创造了整个层次对我来说,我没有获得“MyObject来”。 如此看来,我可以做插入一个新项目的唯一一件事就是看以前的项目,并复制它。 我试过ko.utils.extend功能,但这并不似乎做一个实际的克隆。 它给了我一个对象回来,但是当我更新对象时,它仍然会影响它是从复制的原始对象。
见的jsfiddle 例子
有可能是在映射设置来设置此一方式,但我不能完全明白这一点,只是还没有。
与此同时,你可能只是取消映射对象并将其映射回来,你基本上是做一个副本。
var newJob = ko.mapping.fromJS(ko.mapping.toJS(job));
这将是做就像任何其他的图书馆,“反序列化”和“连载”回来的最简单方法。
我一直在寻找难的好方法使用映射选项做到这一点,并找到了一种方法。
默认情况下,映射插件将采取从源对象的可观察实例和在目标对象使用相同的实例。 因此,实际上,这两个实例将共享相同的观测值(错误?)。 我们需要做的是为每个属性创建一个新的观察到的,复制的值过。
幸运的是,有一个方便的工具函数绘制出每个对象的属性。 然后,我们可以创造我们的价值观的副本初始化新观察到的情况。
// Deep copy
var options = {
create: function (options) {
// map each of the properties
return ko.mapping.visitModel(options.data, function (value) {
// create new instances of observables initialized to the same value
if (ko.isObservable(value)) { // may want to handle more cases
return ko.observable(value);
}
return value;
});
}
};
var newJob = ko.mapping.fromJS(job, options);
请注意,这将是一个浅拷贝,你可能拥有的对象,如果你想有一个深拷贝递归映射。 然而,这将解决您的示例中的问题。
ko.utils.clone = function (obj) {
var target = new obj.constructor();
for (var prop in obj) {
var propVal = obj[prop];
if (ko.isObservable(propVal)) {
var val = propVal();
if ($.type(val) == 'object') {
target[prop] = ko.utils.clone(val);
continue;
}
target[prop](val);
}
}
return target;
};
这里是我的解决方案,希望它帮助。 在这段代码中, obj
将您的视图模型对象。
文章来源: How do I make a deep copy of a knockout object that was created by the mapping plugin