1

好吧,标题可能有点混乱,所以我会解释......

我正在编写一个自定义绑定,我将向其传递一个 observableArray。这个 observableArray 是异步填充的,元素被一个一个推入。

update问题是每次 observableArray 发生突变时都会调用我的自定义绑定(方法)。这是有道理的,但在这种情况下没有帮助,因为这意味着第一个元素被渲染n次,其中n是 observableArray 的长度,第二个元素被渲染n-1次,只有第n 个元素被渲染渲染一次。

任何人都可以解释一种让自定义绑定只做某事的简洁方法

  • observableArray 已完全填充,或
  • 当添加了自定义绑定尚未呈现的元素时?

我可以想出几种方法来解决这个问题,在父视图模型上使用一个额外的属性/可观察作为一个标志,上面写着“完全填充,你可以现在渲染项目”或者每个元素上的一个属性,上面写着“你'已经渲染了我'。然而,这些都很尴尬,特别是 observableArray 中的对象也有 observableArray 属性。

对于这个问题,没有更好的 Knockout/MVVM 解决方案吗?

更新: 为了清楚起见,我正在构建的东西是这样的

<domElmnt data-bind="myBinding: { collection: TypeGroups }" />

在哪里

TypeGroups = ko.observableArray();

并且其中包含的元素TypeGroups是具有可观察属性的另一个视图模型的所有实例。

每次我调用TypeGroups.push(obj)自定义绑定时都会再次调用一次。

4

3 回答 3

2

无法准确判断是否有必要,但如果必须将 customBinding 放在 observableArray 上,我会这样做。

您想要做的是原子更新。有splice和通常的数组拼接一样的方法。

yourArray.splice(atIndex, 0, elem1, elem2, elem3 ...)

但这样它并不是真的有用:

yourArray.splice.apply(yourArray, [index, 0, elem1, elem2, elem3 ...])

这不是真的很漂亮,但我们可以做得更好。

function append(array, values) {
    var params = [array().length, 0];
    params.push.apply(params, values);
    array.splice.apply(array, params);
}

我很确定使用 splice 将自动附加所有元素,而无需多次调用 update 。另一方面,调用array.push.apply(array, values)可能就足够了,不需要拼接。

但!

如果我处于你的位置,我会将绑定从 obserableArray 移动到 observable 数组中的项目。我不知道您为什么在更新后迭代所有项目。如果元素被处理一次,是否有理由多次处理已处理的项目?如果不是,那么自定义绑定可能不会在它应该使用的地方使用。

如果不了解更多关于您的问题的信息,很难说解决问题的最佳方法是什么。

于 2014-01-16T16:07:04.793 回答
0

以下是我解决这个问题的方法:每次调用自定义绑定时,我(安全地)计算已经将多少子元素添加到上下文元素中:

var childCount = 0,
    children = element.childNodes,
    childMax = children.length;
for (var c = 0; c < childMax; c++) {
    if (children[c].nodeType != 3) {
        childCount++;
    }
}

然后,当我遍历指定的 observableArray 时,我使用childCount-从前一个元素计数开始 - 作为起始索引,并从该索引开始循环:

var coll = groupsCollection();    // groupsCollection is the specified observableArray
childMax = coll.length;
for (; childCount < childMax; childCount++) {
    // do something with coll[childCount ], such as using it to add a DOM node
}
于 2014-01-17T09:59:11.260 回答
0

查看 ko.utils.arrayPushAll()。

您将所有对象转储到一个数组中,并通过一个事务将它们全部推送。这将更新一次 UI。

查看 Ryan Niemeyer 实用函数的这篇文章

于 2014-01-16T17:23:11.173 回答