【问题标题】:knockoutjs deep copy observable arrayknockoutjs 深拷贝可观察数组
【发布时间】:2018-08-04 08:42:23
【问题描述】:

我在 Knockout 中有一个可观察数组,例如 data,其中包含具有可观察属性的对象。在我的应用程序的一部分中,我希望允许用户添加到这个数组并最终搞砸它,但如果他们取消将数组恢复到原始状态。

我想到的一个解决方案是创建一个名为 dataCopy 的副本,以在取消时替换原始数组,但这只会创建另一个指向相同基础数据的指针,因此它也会反映所做的更改这不是我想要的。 我尝试通过ko.toJS(data) 将其转换为javascript,这会创建一个数据的js 数组,但是所有对象都失去了它们的可观察属性,当我使用ko.observableArray(dataCopy) 重新创建数据时,应用程序会因为对象的属性不再可观察。

如何创建一个剔除数组的克隆而不是另一个指针?

【问题讨论】:

  • 你可以试试this.activeProducts = ko.observableArray(jQuery.extend(true, {}, products));
  • @NavoneelTalukdar 在这种情况下,可观察的属性将丢失。这和ko.toJS没有太大区别

标签: javascript knockout.js


【解决方案1】:

这是一个示例,说明如何使用 ko mapping plugin 深度复制可观察数组来实现此目的。 我怀疑任何其他复制方法都适合您,例如.sliceko.toJS,因为正如您所提到的,您想要一个深度副本,它可以达到底层对象的可观察属性。

这里的重要部分是函数:

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

这将通过首先将源数组转换为计划 JS 数组然后填充目标数组来进行深度复制,并将其转换为可观察的底层对象属性。

完整的工作示例:

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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 2017-11-25
    • 2012-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多