Knockout.js KnockOutJS-获取“未定义”值,不确定原因

Knockout.js KnockOutJS-获取“未定义”值,不确定原因,knockout.js,Knockout.js,看小提琴手是最好的方式看到这一点。如果您在浏览器中以开发人员模式运行它,如Chrome或FF with FireBug,并运行代码,您将在控制台中看到一个错误。它告诉我,我试图读取的值是未定义的 错误发生在第50行: if (item.Id == self.selectedOfferTypeDetailsType().Id) { self.selectedOfferTypeDetailsType.Id未定义 问题是,你会看到我在其他地方引用了相同的值,在其他地方它似乎工作正常。很明显我错过了

看小提琴手是最好的方式看到这一点。如果您在浏览器中以开发人员模式运行它,如Chrome或FF with FireBug,并运行代码,您将在控制台中看到一个错误。它告诉我,我试图读取的值是未定义的

错误发生在第50行:

 if (item.Id == self.selectedOfferTypeDetailsType().Id) {
self.selectedOfferTypeDetailsType.Id未定义


问题是,你会看到我在其他地方引用了相同的值,在其他地方它似乎工作正常。很明显我错过了什么。。。我的头撞了两天墙,请换一双新眼睛。

在这种情况下,您需要做的是取消对计算属性的评估

<select data-bind="... optionsValue: 'Id', ..."></select>
创建viewModel实例时,self.selectedOfferTypeDetailsType将返回undefined。将DeliverEvaluation设置为true时,计算的报价评估将延迟,直到您真正需要计算的报价值

self.offer = ko.computed({
    read: function () {
        var o = 'Not Found';
        ko.utils.arrayForEach(self.offerTypeDetailsTypes(), function (item) {
            if (item.Id == self.selectedOfferTypeDetailsType().Id) {
                alert('Yay');
            }
        });
        return o;
    },
    deferEvaluation : true
});
我希望这能有所帮助。

问题在于:

self.offerDetails = ko.computed(function() {
    var activeCategories = ko.observableArray();
    ko.utils.arrayForEach(self.offerTypeDetailsTypes(), function (item) {
        if (item.Id == self.selectedOfferType().Id)
            activeCategories.push(item.DisplayName);
    });
    self.selectedOfferTypeDetailsType(activeCategories()[0]); // PROBLEM!
    return activeCategories();
});

self.selectedOfferTypeDetailsType此时被设置为字符串,毫无疑问,当您稍后尝试访问它时,它没有Id属性。

Damien和jaux都有敏锐的眼睛,但在这种情况下,它们只是部分正确。确实,敲除计算在声明后会立即进行评估,以便敲除可以确定您的计算需要订阅哪些其他观测值,但这不是错误发生的时间

<select data-bind="... optionsValue: 'Id', ..."></select>
computed after定义的初始计算正在运行,没有问题。但是,只要调用ko.applyBindings,您的选择就被连接起来,并开始使用视图模型,这时就会发生错误

不寻常的行为 一旦您的第一个id=offerTypes的select被绑定,它会执行一些不寻常的操作:它会立即写入selectedOfferType。这不是绑定选择通常的工作方式。通常,select在用户更改某些内容之前不会写入其值,但在这种情况下,select绑定会立即将值写入SelectedOfferType。容忍我,我会告诉你我是如何发现错误的

让我们开始追踪 offerDetails正在观察SelectedOfferType,因此,一旦您的第一个select被绑定并向SelectedOfferType写入一个新值,offerDetails将运行以检查其值是否也已更改。在offerDetails中,您向selectedOfferTypeDetailsType写入一个值,该值会提醒其订阅者-包括offer在内的订阅者。执行Offer,但您只需在offerDetails中将self.selectedOfferTypeDetailsType设置为null,并且无法读取null的id属性

所以,问题是为什么select在绑定时会向SelectedOfferType写入一个值?答案在于你的约束。当您初始化视图模型时,看起来您正在尝试使用offerTypes中的第二个值预先设置第一个下拉列表:

self.selectedOfferType = ko.observable(self.offerTypes()[1]);
还有你的装订

<select id="offerTypes" data-bind="options: offerTypes, ... value: selectedOfferType"></select>
同意您将该值附加到您的选择。但是,您将self.selectedOfferType设置为self.offerTypes[1]中的对象,但我在上面省略的绑定部分表明,选项的值不是对象,而是“Id”属性中的任何值

<select data-bind="... optionsValue: 'Id', ..."></select>
使用对象填充selectedOfferType,但将optionsValue指定给属性的组合会导致Knockout了解selectedOfferType中的值无效且不可选,因此Knockout会立即使用第一个可能的选项值更新selectedOfferType。在本例中,为“0”

这会触发写操作,这会触发所有订阅者,从而导致您的错误

令人惊叹的那么我该如何解决这个问题呢? 由于您编写的大多数代码都希望在selectedOfferType中有一个对象,因此我只需从您的selectedOfferType中删除optionValue:'Id'


这么冗长的回答怎么样-D

嘿,达米恩,你的回答确实说明了这类错误的一个常见原因,但在这种情况下还有其他原因。看看我的答案,看看导致这个bug的奇怪行为。好吧,那么在一天结束时,结果证明Ryan、Damien和Jaux都是正确的,没有一个解决方案解决了所有问题,但这三个解决方案都需要一起工作。实际上,我找到了OptionValue:Ryan详细描述的问题,但我偶然发现了它。我把整个该死的页面都扔掉了,重新开始,当我一次一个地把东西放回去的时候,我发现了它。Jaux,那是一双锐利的眼睛,我会错过很久的。那是我错过的一些旧代码。Damien,我很想更好地了解这有什么帮助。我之所以给Ryan正确的答案,仅仅是因为他的描述详尽无遗,但如果我可以,你们都可以分享。我同意你的观点,Todd;到处都是点。我以前没有见过这个特别的问题,所以我想我会写一篇关于它的博客文章。在接下来的几天里拜访并登记入住:好主意。而且
这条线需要拆下。不这样做意味着您永远无法更改第二个下拉列表的值。self.SelectedOfferTypeDetailsTypeActivityCategories[0];Ryan,你能联系我吗?Toddhdhd访问gmail.com