计算的 observable 没有被执行

Posted

技术标签:

【中文标题】计算的 observable 没有被执行【英文标题】:computed observable is not being executed 【发布时间】:2012-04-19 15:23:02 【问题描述】:

由于某种原因,当关联值发生变化时,我似乎无法计算 ko.computed 可观察值。

这是一个代表客户的单个奖励​​积分记录的对象

//
// RewardPoints Model
var RewardPointsItemModel = function (data) 
    return 
        DateAwarded: ko.observable((data != null) ? data.DateAwarded : ""),
        Points: ko.observable((data != null) ? data.Points : 0)
    
;

我定义了一个 viewModel,其中包含对“OrderDetailModel”的引用。这个 OrderDetailModel 有一个定义为 ko.observable 的属性,并使用一个新的空 OrderDetailModel 实例进行初始化;用空数组初始化,并应用于由“$OrderDetailForm”引用标识的 html 的适当部分。

$j(function () 
    //
    // initialize global DOM references
    $LoyaltyProgram = $j("#LoyaltyProgram");
    $LoyaltyHistory = $j("#LoyaltyHistory");
    $OrderDetailForm = $j("#OrderDetailForm");
    //
    // define and bind the viewModels
    viewModel = 
        OrderDetailModel: 
            OrderDetail: ko.observable( new OrderDetailModel([]) )
        
    ;
    ko.applyBindings(viewModel.LoyaltyHistoryOrderDetailModel, $OrderDetailForm[0]);

);

这里是“OrderDetailModel”对象的定义。它将一个 RewardPointsItemModel 对象实例(如上定义)的数组作为初始化参数“data”。最终它所做的是维护一个 RewardPointsItemModels 数组并计算每个 RewardPointsItemModels 的 Points 属性的总和。首次加载页面时,会使用空数组(见上文)创建 this 的实例,从而导致计算的“TotalPoints”为 0(零)。

//
// OrderDetail Model
function OrderDetailModel(data) 
    var self    = this;
    this.RewardPoints = ko.observableArray(data);
    this.TotalPoints = ko.computed(function () 
        var points = 0;

        if (self.RewardPoints.length <= 0)
            return points;

        for (var i = 0; i < self.RewardPoints().length; i++) 
            var record = self.RewardPoints()[i];
            points += record.Points();
        
        return points;
    );
;

用户交互执行对返回奖励积分记录列表的 WebAPI 服务的调用,然后将该数据作为“数据”参数传递给下面的回调函数。在回调函数中,我创建了一个新的空数组,然后使用从 WebAPI 调用检索到的记录创建的 RewardPointsItemModel 对象的实例填充它。然后,我在 ko.observable 属性中存储的 OrderDetailModel 的现有实例中替换 ko.observableArray 属性“RewardPoints”中的空数组值... viewModel.OrderDetailModel.OrderDetail ...与我的新的rewardPoints 数组

function Callback(data) 

    var rewardPoints = new Array();
    for (var i = 0; i < data.ServiceModel.length; i++) 
        var model = new RewardPointsItemModel(data.ServiceModel[i]);
        rewardPoints.push(model);
    
    viewModel.OrderDetailModel.OrderDetail().RewardPoints(rewardPoints);
;

此时我希望重新计算 ko.computed 可观察属性“viewModel.OrderDetailModel.OrderDetail().TotalPoints()”,但是当我将跟踪代码放入计算函数中时甚至没有被调用,这表明该函数没有执行以更新值。我的理解是,如果依赖属性(在本例中为 RewardPoints)已更新(从空数组到填充数组),则计算属性应重新评估。

我知道这对我来说解释起来很复杂,所以我希望我已经清楚了。我希望有比我更精通 Knockout 的人能够清楚地理解这一点,并找出为什么初始化后计算值不计算。

【问题讨论】:

应该 (self.RewardPoints.length 【参考方案1】:

您的问题似乎在这里:

if (self.RewardPoints.length <= 0)
        return points;

你需要做的:

if (self.RewardPoints().length <= 0)
        return points;

self.RewardPoints 是一个observableArray,它是一个函数。函数的长度是为函数定义的参数的数量。 observableArray 没有列出任何命名参数,因为它是从参数中读取的,因此值为 0。

因此,您当前的代码始终返回 0,而不是实际访问 observableArray 的值来创建依赖项。

【讨论】:

DOH!!!! Geezus ...我一直在努力记住使用括号!太感谢了。这似乎成功了。

以上是关于计算的 observable 没有被执行的主要内容,如果未能解决你的问题,请参考以下文章

这种奇怪的 C++ 语法有啥作用? [复制]

在哪里订阅 Angular 中的 observable、构造函数或 ngoninit [关闭]

从(服务器发送的)EventSource 创建一个 RxJS Observable

AVCapture​照片​输出为FlashScene Key-Value-Observing

在RxJS中,Observer是否被注入到Observable执行中?

为什么R聚合丢弃数据行?