Knockout computed会为写入但未读取的observable创建依赖项

时间:2013-07-09 10:39:47

标签: javascript knockout.js

我在'小部件'中有这个代码。值是窗口小部件值,另一个是应用程序中其他位置的数据源。即使永远不会读取,计算器也会创建值的订阅。这意味着当我更新值时,运行comp并将值设置回其他..

value = ko.observable(1); // Widgets value
other = ko.observable('a'); // Somewhere else in app

comp = ko.computed(function () {
    value(other());
    doSomeThingElse();
});

value(2);
// comp is run
value() === 'a'; // true

基本上我需要comp才能运行,如果其他的更改。我看到现在有一​​个peek函数,但这只是为了阅读。为什么计算甚至为永远不会读取的observable创建订阅?这非常令人沮丧。有没有办法解决这个问题?

在窗口小部件上使用comp函数从外部源设置数据,窗口小部件的实际布局如下:

new Widget({
    id: 'widget',
    initial: 5,
    observables: {
        data: function () {
            var data = client.get('data'); // observable
            this.value(data);
            this.color(data.length ? 'red' : 'green');
        }
    }
})

创建窗口小部件时,它会根据observables.data进行计算。我们希望保留这个简单的api,而不必进行手动订阅,这会使小部件复杂化。

修改 问题实际上是我的代码错误,上面的例子是为了简化,但实际上切掉了问题。如果对http://jsfiddle.net/dominata/hu6Fr/感兴趣,请看这个小提琴。

经过考虑后,我们将使用此模型而不是纯粹用于副作用的计算机。我同意这更多是如何使用它们。

new Widget({
    id: 'widget',
    initial: 5,
    value: function () {
        return client.get('data');
    },
    color: function () {
        return client.get('data').length ? 'red' : 'green';
    }
})

1 个答案:

答案 0 :(得分:1)

在计算中设置value不会创建订阅。您将订阅other。唯一的问题是,如果您在value中访问doSomethingElse

这是一个小提琴,显示最初评估计算,但在更新value后未评估:http://jsfiddle.net/rniemeyer/exV92/

我同意@nemesv你可能会想要在计算中设置一个observable时要小心。你当前的情况应该有效(除了doSomethingElse中的做法。)

另一种选择可能是使用手动订阅。如果您只想在value更改时更新other,则可以执行以下操作:

other.subscribe(function(newValue) {
    value(newValue);
    doSomethingElse();
});

通过手动订阅,只有在特定的observable发生更改时才会触发,因此您不必担心要访问的依赖项。