背景
我正在尝试构建一个成绩簿应用程序,主要作为学习练习。目前,我有两个模型、一个学生和一个作业。我决定将所有与分数相关的信息存储在学生内部,而不是存储在每个作业中。也许有更好的方法。
无论如何,我已经有了每个学生的平均分,即她在类的成绩。我现在想要计算每项作业的平均分数。这就是我遇到麻烦的地方,因为它有点棘手。我目前正在使用以下方法:
JS Bin (entire project): http://jsbin.com/fehoq/84/edit
JS
var _this = this;
...
// get index i of current assignment;
// then, for each student, grab her grade for assignment i;
// add each grade at i, then divide by # of students;
// return this value (the mean);
this.workMean = ko.computed(function (work) {
var i = parseFloat(_this.assignments.indexOf(work));
var m = 0;
var count = 0;
ko.utils.arrayForEach(_this.students(), function (student) {
if (!isNaN(parseFloat(student.scores()[i]))) {
m += parseFloat(student.scores()[i]);
} else {
count += 1;
}
});
m = m / (_this.students().length - count);
return m.toFixed(2);
});
我通过以下方式将其绑定(bind)到 HTML:
HTML
<tbody>
<!-- ko foreach: students -->
<tr>
<td><input data-bind="value: fullName + ' ' + ($index()+1)"/></td>
<!-- ko foreach: scores -->
<td><input data-bind="value: $rawData"/></td>
<!-- /ko -->
<td data-bind="text: mean" />
<td><input type="button" value="remove" data-bind="click: $root.removeStudent.bind($root)". /></td>
</tr>
<!-- /ko -->
<tr>
<td>Class Work Average</td>
<!-- ko foreach: assignments -->
<td data-bind="text: $root.workMean"></td>
<!-- /ko -->
</tr>
</tbody>
问题是我在这里所做的事情 - 我认为是 workMean()
方法 - 完全破坏了我的应用程序。在尝试调试时,我注意到,如果我简单地注释掉整个方法 save i
,然后返回 i
并将其绑定(bind)到较低的 foreach: assignments
,它始终返回 -1
(对于每个分配)。
Knockout 文档告诉我,这意味着当我调用 indexOf
时没有匹配项,但我不知道为什么。感谢指导。
最佳答案
除了 DCoder identified 的问题- observables 不接受参数 -,你在这里还有另一个错误:
score = parseFloat(student.scores()[i]);
应该是
score = parseFloat(student.scores()[i]());
您访问的可观察数组的第 n 个(或第 i 个)元素本身就是一个可观察的,因此在此之前,您将函数传递给 parseFloat
,它总是产生 NaN。
这是一个工作版本:http://jsbin.com/lejezuhe/3/edit
顺便说一句:DCoders 更改后,
<td data-bind="text: $root.workMean($data, $index())"></td>
绑定(bind)一个普通函数,而不是一个可观察的函数。那么为什么这仍然有效?
RP Niemeyer, one of the Knockout core members writes :
In Knockout, bindings are implemented internally using dependentObservables, so you can actually use a plain function in place of a dependentObservable in your bindings. The binding will run your function inside of a dependentObservable, so any observables that have their value accessed will create a dependency (your binding will fire again when it changes).
(在早期版本的 Knockout 中,计算的可观察量过去称为“dependentObservables”)
对于这些类型的问题,熟悉调试器(例如 Chrome Developer Tools 中的调试器)确实很有帮助。 。能够逐行单步执行代码并查看实际包含的参数和变量非常有帮助。
Chrome Knockout context debugger在调试绑定(bind)时值得拥有,因为您可以单击任何 DOM 元素并查看绑定(bind)上下文:
最后,使用 ko.dataFor()
控制台中的 允许您查看绑定(bind)到 DOM 的任何现有 Knockout 模型和 View 模型:
在 Chrome 控制台中,$0
始终是对您当前在“元素”面板中选择的 DOM 元素的引用 - 这里是 <td>
.
关于javascript - knockout JS : indexOf always returns -1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23299194/