3

我一直在查看knockout's的文档observableArray,但我无法弄清楚如何使用数组执行最基本的操作之一:按索引分配值。

我尝试过的事情:(给定oa = ko.observableArray([1,2,3])

  • oa(1, 10);
  • oa[1] = 10;
  • oa()[1] = 10;
  • oa.splice(1, 1, 10);

最后一个似乎有效,但我担心这.splice()可能效率低下,因为它必须关注转移所有后续值。我宁愿只做简单的基于索引的分配。

创建了一个显示 observableArray 很奇怪的 jsfiddle。

<ol data-bind="foreach: list">
    <li data-bind="text: $data"></li>
</ol>

<script>
    var model = {
        list: ko.observableArray([3, 5, 7])
    };

    ko.applyBindings(model);

    setTimeout(function() {
        model.list()[1] = 55;
        model.list.push(99);
        model.list()[2] = 77;
    }, 2000);
</script>
4

3 回答 3

6

修改后在您的 observable 上应用valueHasMutated属性

setTimeout(function() {
    model.list()[1] = 55;
    model.list.push(99);
    model.list()[2] = 77;
    model.list.valueHasMutated();
}, 2000);
于 2013-08-05T22:02:11.293 回答
3

Observable 数组在调用 mutating 方法或使用新数组初始化时通知其侦听器更改(并因此导致相应的视图更新)。

oa()[i] = x;
oa(oa());

您可以将其分解为扩展方法:

ko.observableArray.fn.setItem = function(index, newValue) {
    var items = this();
    items[index] = newValue;
    this(items);
};

foreach绑定足够智能,可以检测到只有一个元素发生了变化,而无需再次渲染其他节点。

于 2013-08-05T04:07:16.683 回答
1

您在小提琴中分配值的方式效果很好。如果您执行console.log()model.list() 对象,您实际上可以看到数组的值已正确更新。

要记住的关键是文档中的以下内容:

关键点:一个 observableArray 跟踪数组中有哪些对象,而不是那些对象的状态

简单地将一个对象放入 observableArray 并不能使该对象的所有属性本身都可观察。当然,如果您愿意,您可以使这些属性可观察,但这是一个独立的选择。observableArray 只跟踪它持有的对象,并在添加或删除对象时通知侦听器。

这就是您的视图没有使用索引 2 中的新值更新的原因,因为它不是可观察的值。像这样的东西(又快又脏)会起作用:

var model = {
    list: ko.observableArray([ko.observable(3), ko.observable(5), ko.observable(7)])
};
model.list()[2](77); // Yeah, looks weird.
于 2013-08-05T04:05:06.980 回答