简体   繁体   English

Knockout.js深度复制可观察数组

[英]knockoutjs deep copy observable array

I have an obeservable array in Knockout, say data that contains objects with observable properties. 我在淘汰赛中有一个可观察的数组,比如说包含具有可观察属性的对象的data In one part of my application I want to allow users to add to this array and ultimately mess about with it, but if they cancel to revert the array to the original state. 在我的应用程序的一部分中,我希望允许用户添加到该数组中并最终使其混乱,但是如果他们取消操作,则将数组还原为原始状态。

One solution I though of is to create a copy called dataCopy that replaces the original array in the event of cancellation, but this only creates another pointer to the same underlying data, so it will also reflect the changes that were made which is not what I want. 我的一个解决方案是创建一个名为dataCopy的副本,该副本在取消的情况下将替换原始数组,但这只会创建另一个指向同一基础数据的指针,因此它也将反映所做的更改,这不是我所做的想。 I've tried converting it to javascript, via ko.toJS(data) and this creates a js array of the data, however all of the objects lose their observable properties and when I re-create the data using ko.observableArray(dataCopy) the app falls over as the properties of the objects are no longer observable. 我尝试通过ko.toJS(data)将其转换为javascript,这会创建ko.toJS(data)的js数组,但是所有对象都会丢失其可观察的属性,当我使用ko.observableArray(dataCopy)重新创建数据时由于对象的属性不再可见,因此该应用程序崩溃了。

How can I create a clone of a knockout array rather than another pointer? 如何创建基因剔除数组而不是其他指针的克隆?

This is an example of how you could achieve this using the ko mapping plugin for deeply copying your observable arrays. 这是使用ko映射插件深度复制可观察数组的方法的示例。 I doubt any other method of copying would work for you such as .slice or ko.toJS since as you mentioned you want a deep copy which goes as far as the underlying object's observable propertieš. 我怀疑任何其他复制方法都可以对您.slice ,例如.sliceko.toJS因为正如您所提到的,您需要一个深层复制,该复制尽可能深入到基础对象的可观察特性。

The important part here is the function : 这里的重要部分是功能:

function obsArrDeepCopy(from, to) {
  ko.mapping.fromJS(ko.toJS(from), {}, to);
}

Which will do the deep copy by first converting the source array to a plan JS array and then populate the target array converting to observables the underlying object properties. 通过首先将源数组转换为计划JS数组,然后填充目标数组以转换为可观察的基础对象属性,它将进行深度复制。

Full working example: 完整的工作示例:

 function Person(name) { this.name = ko.observable(name); } var viewModel = { people: ko.observableArray([ new Person("Annabelle"), new Person("Bertie"), new Person("Charles") ]), peopleCopy: ko.observableArray(), newName: ko.observable(''), addPerson: function() { this.peopleCopy.push(new Person(this.newName())) }, commit: function() { obsArrDeepCopy(this.peopleCopy, this.people) }, cancel: function() { obsArrDeepCopy(this.people, this.peopleCopy) }, }; ko.applyBindings(viewModel); obsArrDeepCopy(viewModel.people, viewModel.peopleCopy); function obsArrDeepCopy(from, to) { ko.mapping.fromJS(ko.toJS(from), {}, to); } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script> <h2> Initial </h2> <ul data-bind="foreach: people"> <li> <span data-bind="text: name" /> </li> </ul> <br/><br/> <h2> Copy </h2> <ul data-bind="foreach: peopleCopy"> <li> <span data-bind="text: name" /> </li> </ul> <input type="text" data-bind="textInput: newName" /> <button type="button" data-bind="click: addPerson"> Add </button> <br/><br/> <button type="button" data-bind="click: commit"> Commit </button> <button type="button" data-bind="click: cancel"> Cancel </button> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM