1

我在“小部件”中有此代码。Value 是小部件的值,other 是来自应用程序其他地方的数据源。计算值创建订阅,即使它从未被读取。这意味着当我更新值时,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 功能,但仅供阅读。为什么计算甚至为从未读取的可观察对象创建订阅?这非常令人沮丧。有没有办法解决?

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';
    }
})
4

1 回答 1

1

计算中的设置value不会创建订阅。您将订阅other. 唯一的问题是您是否value作为doSomethingElse.

这是一个小提琴,表明计算最初是评估的,但在更新后没有评估:http value: //jsfiddle.net/rniemeyer/exV92/

我同意@nemesv 的观点,您可能希望在计算中设置一个可观察对象时要小心。您当前的案例应该有效(除非在 中所做的事情doSomethingElse)。

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

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

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

于 2013-07-09T13:22:38.280 回答