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