如何制作由映射插件创建的敲除对象的深层副本 [英] How do I make a deep copy of a knockout object that was created by the mapping plugin

查看:17
本文介绍了如何制作由映射插件创建的敲除对象的深层副本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的场景.我正在使用敲除映射插件为我创建一个可观察的视图模型层次结构.我的层次结构中有嵌套的元素.在层次结构中的特定点,我想放置一个添加按钮以在 observablearray 中插入该元素的新空白副本.问题是我不能只说whateverArray.push(new MyObject()).

Here's my scenario. I'm using the knockout mapping plugin to create an observable viewmodel hierarchy for me. My hierarchy has nested elements in it. At a particular point in the hierarchy I want to put an Add button to insert a new blank copy of that element in the observablearray. The problem is I can't just say whateverArray.push(new MyObject()).

由于映射插件实际上为我创建了整个层次结构,因此我无权访问MyObject".因此,插入新项目似乎唯一能做的就是查看以前的项目并复制它.我尝试了 ko.utils.extend 函数,但这似乎不是真正的克隆.它给了我一个对象,但是当我更新那个对象时,它仍然影响从它复制过来的原始对象.

Since the mapping plugin actually created the whole hierarchy for me, I don't have access to "MyObject". So it seems the only thing I can do to insert a new item is to look at a previous item and copy it. I tried the ko.utils.extend function, but that doesn't appear to be making an actual clone. It gives me an object back, but when I update that object it still affects the original object that it was copied from.

参见 jsfiddle 示例

See jsfiddle example

推荐答案

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

There might be a way to set this up in the mapping settings but I can't quite figure that out just yet.

与此同时,您可以取消映射对象并将其映射回来,这样您实际上就是在制作副本.

In the mean time, you could just unmap the object and map it back so you are essentially making a copy.

var newJob = ko.mapping.fromJS(ko.mapping.toJS(job));

这将是最简单的方法,就像任何其他库一样,反序列化"并再次序列化".

This will be the easiest way to do it just like any other library, "deserialize" and "serialize" back again.

我一直在寻找一种使用映射选项的好方法,并找到了一种方法.

I was looking hard for a nice way to do this using the mapping options and found a way.

默认情况下,映射插件将从源对象中获取可观察的实例并在目标对象中使用相同的实例.所以实际上,两个实例将共享相同的可观察对象(错误?).我们需要做的是为每个属性创建一个新的 observable 并复制这些值.

By default, the mapping plugin will take the observable instances from the source object and use the same instance in the target object. So in effect, both instances will share the same observables (bug?). What we needed to do was create a new observable for each property and copy the values over.

幸运的是,有一个方便的实用函数来映射对象的每个属性.然后,我们可以创建新的 observable 实例,并使用值的副本进行初始化.

Fortunately, there is a handy utility function to map out each of the properties of an object. We can then create our new observable instances initialized with copies of the values.

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

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

Note that this will be a shallow copy, you'll probably have to recursively map the objects if you want a deep copy. This will fix the problem in your example however.

这篇关于如何制作由映射插件创建的敲除对象的深层副本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆