KnockoutJS:将一个 observble 数组作为参数传递给另一个会绑定它们吗?

KnockoutJS: Does passing one observble array as a parameter to another bind them?

我的应用程序中有两个可观察数组,我将一个作为参数传递给另一个,

model.arrayone(model.arrayTwo);

我注意到我在 arrayOne 中输入的内容会自动进入 arrayTwo,这是否意味着它们被绑定在一起

如果 model.arrayTwo 是 ko.observableArray 并且 model.arrayone 是 ko.observableArray 那么做 model.arrayone(model.arrayTwo); 将分配 model.arrayTwo 作为对你的可观察 model.arrayone。这并不意味着它们是绑定的,这意味着它们引用了内存中的同一个地方..

发生的事情是两个可观察数组都绑定到同一个底层数组。可观察数组基本上是标准 javascript 数组的包装器,因此当您使用另一个可观察数组初始化一个可观察数组时,它们将成为相同数据的反映。

它们不是 "bound" 在剔除数据绑定意义上,但它们是绑定的,因为它们每个都引用了相同的源数据。

您所描述的行为

你的做法有点奇怪。这是一个复制品:

const arr1 = ko.observableArray([1]);
const arr2 = ko.observableArray([2]);

arr2(arr1);
arr2.push(2);

console.log(arr1()); // [ 1, 2 ]
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

为什么有效

由于 pushko.observableArray 实施,此行为有效。此方法的工作方式是,它 窥视 可观察数组的内部值并对该对象调用 push 方法。来自消息来源:

ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], 
  function (methodName) {
    ko.observableArray['fn'][methodName] = function () {
        // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
        // (for consistency with mutating regular observables)
        var underlyingArray = this.peek();
        this.valueWillMutate();
        this.cacheDiffForKnownOperation(underlyingArray, methodName, arguments);
        var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
        //                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        this.valueHasMutated();
        // The native sort and reverse methods return a reference to the array, but it makes more sense to return the observable array
        // instead.
        return methodCallResult === underlyingArray ? this : methodCallResult;
    };
});

source

现在,您可以想象,这将导致 push 方法被转发,直到不再有可观察的数组。即:

  1. 致电arr2.push
  2. observableArray arr2 执行 .peek() 并找到对 observbaleArray arr1
  3. 的引用
  4. 致电arr1.push
  5. observableArray arr1 执行 .peek() 并找到对 常规 数组 [1]
  6. 的引用
  7. Array.prototype.push[ 1 ] 上添加 2 最终成为 [ 1, 2 ]

然后:

  1. 评价arr1returns[ 1, 2 ]

为什么这样嵌套 observableArray 是错误的:

当使用 nullundefined 或数组实例以外的任何对象构造可观察数组时,您会收到以下方便的错误消息:

try {
  ko.observableArray(ko.observableArray([]));
} catch(err) {
  console.log(err.message);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

设置一个可观察数组时,不再执行此检查(可能是因为性能?)。该规则仍然适用:

  • 仅使用 observableArrays 来保存数组
  • 使用常规 observables 做其他事情