【问题标题】:How to deep copy a observable array into normal jquery array如何将可观察数组深度复制到普通 jquery 数组中
【发布时间】:2016-11-02 01:58:58
【问题描述】:

我有一个可观察数组嵌套在另一个可观察数组下,这个数组绑定到 UI。

单击按钮时,我将主可观察数组复制到 jquery 数组并进行一些操作,但是当我更改新 jquery 数组时,我的旧可观察数组项正在更改。

下面是sn-p。

  1. 可观察数组

    var masterArray = ko.observableArray([{"name" : "Tom",
                "lastName" : "Jerry",
                "license" : ko.observableArray([1,2,3])},
                {"name" : "Jack",
                "lastName" : "Sparrow",
                "license" : ko.observableArray([4,5,6])}]);
    
  2. 深度复制到普通的 Jquery 数组

    var clonedArr = $.extend(true, [], masterArray());
    
  3. 更改新数组中的值会影响旧数组。

       clonedArr[0].license(7);
       console.log("after deep copy: "+ masterArray()[0].license())
    

我做错了吗?见 jsfiddle https://jsfiddle.net/hdrrd7gj/

【问题讨论】:

  • 我认为您必须手动查看源可观察数组,以查看其子内容是原始数据还是对象,并且需要确定克隆逻辑。 $.extend() 真的不知道淘汰赛框架。所以你必须为这种深度克隆编写自己的逻辑。
  • 你真的应该编辑你的旧问题而不是发布一个问题。 stackoverflow.com/questions/38109341/…

标签: jquery arrays knockout.js


【解决方案1】:

jQuery 的深度扩展将正确处理基元、对象和数组。但是,您的 license 属性不是这些。这是一个函数:

var license = ko.observableArray([1, 2, 3]);
console.log("Type of license: " + typeof license);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

这意味着 jQuery 将无法理解如何克隆它,即使它非常简单:

var cloneObsArray = function(obsArray) {
  var innerArrayClone = obsArray().slice();
  return ko.observableArray(innerArrayClone);
};

var originalArray = [1,2,3];
var originalObsArray = ko.observableArray(originalArray);
var clonedObsArray = cloneObsArray(originalObsArray);

// Test if the clone is actually a clone
originalObsArray.push(4);
clonedObsArray.pop();

console.log("Data source: ", originalArray);
console.log("Original: ", originalObsArray());
console.log("Cloned: ", clonedObsArray());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

结论:如果你想克隆一个包含可观察属性的对象,你需要一个自定义的克隆方法。在纯 JavaScript 中:

var innerCloneMethod = function(obj) { /* todo */ };
var masterArray = ko.observableArray([ /* .... */ };
var clonedArray = masterArray()
  .map(innerCloneMethod)          // Returns a new array with cloned inner objects

快速克隆淘汰视图模型的一种方法是使用ko.mapping 插件。这个插件有 toJS 方法来创建一个普通对象,fromJS 把一个普通对象转换成一个新的视图模型。

var innerCloneMethod = function(obj) {
  return ko.mapping.fromJS(ko.mapping.toJS(obj))
};

var original = {
  a: ko.observable(1),
  b: 2
};

var clone = innerCloneMethod(original);

original.a(2);
console.log("Original a: " + original.a());
console.log("Clone a: " + clone.a());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>

这里的缺点是您需要一个自定义选项对象来防止 namelastName 被转换为 observables。

就个人而言,我会创建一个带有namelastNamelicenses 属性的UserViewModel,以及一个返回具有相似值的new UserViewModelclone 方法。

【讨论】:

    猜你喜欢
    • 2016-11-01
    • 1970-01-01
    • 2018-01-28
    • 2017-10-16
    • 1970-01-01
    • 2018-08-04
    • 2019-06-04
    • 1970-01-01
    • 2021-02-22
    相关资源
    最近更新 更多