Javascript KnockoutJS计算可观测未定义
我有一个非常简单的knockoutjs脚本。我的视图模型包含一个名为“modules”的属性,它是一个字符串数组。如果我有这样一个foreach列表,它会为每个项目打印一个模块列表:Javascript KnockoutJS计算可观测未定义,javascript,knockout.js,Javascript,Knockout.js,我有一个非常简单的knockoutjs脚本。我的视图模型包含一个名为“modules”的属性,它是一个字符串数组。如果我有这样一个foreach列表,它会为每个项目打印一个模块列表: <tbody data-bind="foreach: items"> <tr> <td data-bind="text: modules"></td> </tr> </tbody> 我不确定,但如果你这样做会怎
<tbody data-bind="foreach: items">
<tr>
<td data-bind="text: modules"></td>
</tr>
</tbody>
我不确定,但如果你这样做会怎么样:
function AppViewModel(data) {
var self = this;
ko.mapping.fromJS(data, {}, this);
this.numModules = ko.computed(function() {
return self.modules().length;
});
};
$.getJSON("/api/items", function(data) {
var viewModel = new AppViewModel(data);
ko.applyBindings(viewModel);
});
function AppViewModel(data) {
var self = this;
this.modules = ko.obeservableArray();
ko.mapping.fromJS(data, {}, this.modules());
this.numModules = ko.computed(function() {
return self.modules().length;
});
};
我不确定,但如果你这样做会怎么样:
function AppViewModel(data) {
var self = this;
ko.mapping.fromJS(data, {}, this);
this.numModules = ko.computed(function() {
return self.modules().length;
});
};
$.getJSON("/api/items", function(data) {
var viewModel = new AppViewModel(data);
ko.applyBindings(viewModel);
});
function AppViewModel(data) {
var self = this;
this.modules = ko.obeservableArray();
ko.mapping.fromJS(data, {}, this.modules());
this.numModules = ko.computed(function() {
return self.modules().length;
});
};
在这种情况下,可能是计算对象试图在属性实际存在之前进行计算。默认情况下,ko.computed上未设置的一个参数是deferEvaluation参数……设置此参数后,computed将不会尝试在AppViewModel初始化时进行计算
this.numModules = ko.computed({
read: function() {
return self.modules().length;
},
deferEvaluation: true
);
更为挑剔的是,如果您定义了“self=this”,那么在下一行中使用“this”的上下文设置您的计算,为什么要定义“self”?在这种情况下,可能是计算程序在属性实际存在之前尝试计算。默认情况下,ko.computed上未设置的一个参数是deferEvaluation参数……设置此参数后,computed将不会尝试在AppViewModel初始化时进行计算
this.numModules = ko.computed({
read: function() {
return self.modules().length;
},
deferEvaluation: true
);
更为挑剔的是,如果您定义“self=this”,那么在下一行中,使用“this”上下文设置您的计算结果,为什么要定义“self”?问题在于,您在ViewModel的根上定义
numModules
,而您试图执行的计算是在每个项的模块属性上进行的
因此,self.modules
确实是未定义的,无法调用,因为self
引用根对象,而modules
是每个项的属性
请尝试以下方法:
function AppViewModel(data)
{
var self = this;
ko.mapping.fromJS(data, {}, this);
// defining the computed function on each 'item'
for (var i in self.items())
{
self.items()[i].numModules = ko.computed(function()
{
return this.modules().length;
}, self.items()[i]);
}
};
或者这样:
// defined on $root
self.numModules = function(item) {
return item.modules().length;
}
// but passing 'item' upon invocation
<td data-bind="text: $root.numModules($data)"></td>
//在$root上定义
self.numModules=函数(项){
返回项.modules().length;
}
//但在调用时传递“项”
问题在于,您在ViewModel的根上定义numModules
,而您试图执行的计算是在每个项的模块属性上进行的
因此,self.modules
确实是未定义的,无法调用,因为self
引用根对象,而modules
是每个项的属性
请尝试以下方法:
function AppViewModel(data)
{
var self = this;
ko.mapping.fromJS(data, {}, this);
// defining the computed function on each 'item'
for (var i in self.items())
{
self.items()[i].numModules = ko.computed(function()
{
return this.modules().length;
}, self.items()[i]);
}
};
或者这样:
// defined on $root
self.numModules = function(item) {
return item.modules().length;
}
// but passing 'item' upon invocation
<td data-bind="text: $root.numModules($data)"></td>
//在$root上定义
self.numModules=函数(项){
返回项.modules().length;
}
//但在调用时传递“项”
我发现解决这个问题的最简单方法是在html中这样做,而不添加任何特殊的js代码:
<td data-bind="text: modules().length"></td>
我发现解决这个问题的最简单方法是在html中这样做,而不添加任何特殊的js代码:
<td data-bind="text: modules().length"></td>
在您的AppViewModel中,您没有模块
。这个想法是通过使用映射插件,模型由数据定义。在您的AppViewModel中,您没有模块
。这个想法是通过使用映射插件,模型由数据定义。在您的第一个示例中,我希望避免在每个项目上定义函数。我宁愿以某种方式在模型上定义它。在最后一个示例中,函数真的与ko.computed相同吗?在ko.computed
上使用函数是很常见的,在您的情况下也可以正常工作。有关更多信息,请参阅。在迄今为止的答案中,您的最后一个答案是唯一有效的。html中的$root和$data语法看起来并不像简单的“numModules”那么好。如果您想要的是漂亮干净的代码,最好是实际定义您的项目视图模型(function item(){this.modules=…}
)不要依赖ko.mapping
从任意数据动态创建对象。在第一个示例中,我希望避免在每个项上定义函数。我宁愿以某种方式在模型上定义它。在最后一个示例中,函数真的与ko.computed相同吗?在ko.computed
上使用函数是很常见的,在您的情况下也可以正常工作。有关更多信息,请参阅。在迄今为止的答案中,您的最后一个答案是唯一有效的。html中的$root和$data语法看起来并不像简单的“numModules”那么好。如果您想要的是漂亮干净的代码,最好是实际定义您的项目视图模型(function item(){this.modules=…}
)不要依赖于ko.mapping
从任意数据动态创建对象。我明白了…仍然没有理由不在别处使用self,因为已经定义了它。我明白了…仍然没有理由不在别处使用self,因为已经定义了它。