Knockout JS:indexOf总是返回-1? [英] Knockout JS: indexOf always returns -1?

查看:280
本文介绍了Knockout JS:indexOf总是返回-1?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景



我正在尝试构建一本成绩册应用程序,主要是作为一种学习练习。目前,我有两个模型,一个学生和一个作业。我决定将所有分数相关的信息存储在学生中,而不是每个作业。也许有更好的方法。

无论如何,我已经有了每个学生的平均分数,即她在班上的成绩。我现在正在想要计算每个作业的平均分数。这是我遇到麻烦的地方,因为它有点棘手。我正在使用以下方法:


JS Bin (整个项目): http://jsbin.com/fehoq/84/edit




JS



  var _this = this; 
...

//获取当前任务的索引i;
//然后,为每个学生,抓住她的成绩分配我;
//在i上添加每个成绩,然后除以#的学生;
//返回此值(均值);

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);
});

我用下面的方式将它绑定到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 =buttonvalue =removedata-bind =click:$ root.removeStudent.bind($ root)。 />< / TD>
< / tr>
<! - / ko - >
< tr>
< td>班级平均值< / td>
<! - ko foreach:assignments - >
< td data-bind =text:$ root.workMean>< / td>
<! - / ko - >
< / tr>
< / tbody>

问题在于我在这里做的事 - 我认为它是 workMean()方法 - 完全打破我的应用程序。在尝试调试的时候,我注意到如果我只是将整个方法注释掉,保存 i ,然后返回 i 并绑定它低于 foreach:assignments ,它始终返回 -1 (对于每个赋值)。



Knockout文档告诉我,当我调用 indexOf 时意味着没有匹配,但我失去了为什么。引导赞赏。

 <$> c $ c> 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> 

绑定一个正常的函数,而不是可观察的。那么,为什么这仍然有效?



RP Niemeyer,Knockout核心之一成员写道:


在Knockout中,绑定是使用dependentObservables在内部实现的,所以您实际上可以使用普通函数绑定中的dependentObservable。绑定将在dependencyObservable内部运行你的函数,所以任何具有它们的值的observable都会创建一个依赖项(当你的绑定发生变化时它会再次激发)。

(在早期版本的Knockout中曾经被称为dependentObservables的计算的observables)



对于这些类型的问题,它确实有助于熟悉诸如中的调试器Chrome开发者工具。能够逐行浏览代码并查看实际包含的参数和变量非常有用。



,因为您可以点击任何DOM元素并查看绑定上下文:



最后,在控制台中使用 ko.dataFor()您现有的Knockout模型和视图模型绑定到DOM:





在Chrome控制台中, $ 0 始终是对您所拥有的DOM元素的引用目前已在元素面板中选择 - 此处为< td>


Background

I'm trying to build a gradebook app, mostly as a learning exercise. Currently, I have two models, a student, and an assignment. I decided to store all score-related information inside the student rather than with each assignment. Perhaps there's a better approach.

Regardless, I already have the average score for each student, i.e., her grade in the class. I'm now at the point where I want to calculate the average score on each assignment. This is where I run into trouble, as it's slightly trickier. I'm currently using the following method:

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);   
    });

And I'm binding this to the HTML in the following way:

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>    

The problem is that something I'm doing here - and I think it's the workMean() method - is completely breaking my app. While trying to debug, I noticed that if I simply comment out the entire method save i, then return i and bind it to the lower foreach: assignments, it consistently returns -1 (for each assignment).

The Knockout docs tell me that means there's no match when I call indexOf, but I'm lost as to why. Guidance appreciated.

解决方案

Besides the issue that DCoder identified — observables not taking parameters -, you had another bug here:

score = parseFloat(student.scores()[i]);

should have been

score = parseFloat(student.scores()[i]());

The nth (or i-th) element of the observable array you access there is itself an observable, so before, you where passing a function to parseFloat, which always yields NaN.

Here is a working version: http://jsbin.com/lejezuhe/3/edit

By the way: after DCoders changes,

<td data-bind="text: $root.workMean($data, $index())"></td>

binds against a normal function, not an observable. So why does this still work?

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).

(computed observables used to be called "dependentObservables" in earlier versions of Knockout)

For these type of issues, it really helps to be familiar with a debugger such as the one in the Chrome Developer Tools. Being able to step through your code line by line and seeing what arguments and variables actually contain is immensely helpful.

The Chrome Knockout context debugger is worthwhile to have when debugging bindings, because you can click on any DOM element and see the binding context:

Lastly, using ko.dataFor() in the console allows you to poke around any of your existing Knockout models and viewmodels bound to the DOM:

In the Chrome console, $0 is always a reference to the DOM element you have currently selected in the Elements panel - here, a <td>.

这篇关于Knockout JS:indexOf总是返回-1?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆