这是我的情况。我正在使用基因 knockout 映射插件为我创建一个可观察的viewmodel层次结构。我的层次结构中有嵌套的元素。在层次结构中的某个特定点,我想添加一个“添加”按钮,以将该元素的新空白副本插入到observablearray中。问题是我不能只说出whatArray.push(new MyObject())。

由于映射插件实际上为我创建了整个层次结构,因此我无权访问“MyObject”。因此,插入新项目似乎唯一可以做的就是查看先前的项目并将其复制。我尝试了ko.utils.extend函数,但似乎并没有进行实际的克隆。它给了我一个对象,但是当我更新该对象时,它仍然会影响复制它的原始对象。

参见jsfiddle example

最佳答案

可能有一种方法可以在映射设置中进行设置,但是我还不太清楚。

同时,您可以仅取消映射对象并将其映射回原来的位置,因此实际上是在制作副本。

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);

请注意,这将是一个浅拷贝,如果想要深表副本,则可能必须递归映射对象。但是,这将解决您的示例中的问题。

关于javascript - 如何制作由映射插件创建的基因 knockout 对象的深拷贝,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12333915/

10-12 13:05