Knockout arrayForEach未定义属性

时间:2015-08-06 13:44:17

标签: javascript function knockout.js

我在尝试从敲除可观察数组中的每个项目中获取数字并将数字加在一起并将其分配给另一个计算变量时遇到问题。这就是我现在所拥有的......

Semesters: ko.observableArray([
    {
        semesterName: "Fall",
        semesterCode: "300",
        PlannedCourses: ko.observableArray([]),
        totalCredits: ko.computed(function(){
            var total = 0;
            ko.utils.arrayForEach(this.PlannedCourses, function (course) {
                total += course.MinHours();
            });

            return total;
        }),
    },
    ...

我要做的是,在totalCredits变量中,我试图遍历PlannedCourses数组并获取每个项目的MinHours变量并将它们一起添加到total变量中。然后我将它返回到Semesters数组中的totalCredits项。我遇到的问题是在ko.utils.arrayForEach部分获取PlannedCourses变量。我得到了一个未定义的东西,我不知道为什么。我认为这是一个简单的语法错误,但我看不出有什么问题。

PlannedCourses可观察数组是一个动态对象,可以正确获取PlannedCourses列表。它是在自身的上下文中定义的,但我没有正确地将它传递给totalCredits计算函数。

我希望这很清楚。谢谢你的帮助!

注意:所有其余代码都按预期工作。唯一不起作用的部分是totalCredits计算函数。我不确定ko.utils.arrayForEach中的任何内容是否正常工作,因为我无法做到这一点。

3 个答案:

答案 0 :(得分:4)

您需要更改填充Semesters可观察数组的方式以使用构造函数来获取对this的正确范围的引用:

function semester(name, code) {
    this.Name = name;
    this.Code = code;
    this.PlannedCourses = ko.observableArray([]);
    this.totalCredits = ko.computed(function(){
        var total = 0;
        ko.utils.arrayForEach(this.PlannedCourses(), function (course) {
            //Note the change to "this.PlannedCourses()" above to get the underlying array
            total += course.MinHours();
        });

        return total;
    }, this); //now we can pass "this" as the context for the computed
}

了解我们现在如何将对象传递给ko.computed的第二个参数,以用作内部函数中this的上下文。有关详细信息,请参阅淘汰文档:Managing 'this'

然后在填充数组时创建semester的新实例:

Semesters: ko.observableArray([
    new semester("Fall", "300"),
    new semester(...)
]);

这种方法也意味着你有一个一致的方法来创建你的semester对象(计算只为一件事定义一次),而不是在你原本可能有的任何重复中加入拼写错误等。

答案 1 :(得分:0)

范围(这个)不是你想象的那样。

请参阅http://knockoutjs.com/documentation/computedObservables.html

尝试添加您的上下文,如下所示:

Semesters: ko.observableArray([
{
    semesterName: "Fall",
    semesterCode: "300",
    PlannedCourses: ko.observableArray([]),
    totalCredits: ko.computed(function(){
        var total = 0;
        ko.utils.arrayForEach(this.PlannedCourses, function (course) {
            total += course.MinHours();
        });

        return total;
    }, this), // new context passed in here
},
...

执行此操作会将数组项本身的上下文传递到计算函数中。

编辑: 您可能需要访问循环中的Semesters对象,并添加一些方法来引用当前项:

Semesters: ko.observableArray([
{
    semesterName: "Fall",
    semesterCode: "300",
    PlannedCourses: ko.observableArray([]),
    totalCredits: ko.computed(function(){
        var total = 0;
        for( var i = 0, len = Semesters().length; i < len; i++ ) {
            // check current array item, possibly add an id?
            if( Semesters()[i].semesterName === "Fall" &&
                Semesters()[i].semesterCode === "300" ) {

                ko.utils.arrayForEach(Semesters()[i].PlannedCourses, function (course) {
                   total += course.MinHours();
                });
                break; // done searching
            }
        }

        return total;
    })
},

答案 2 :(得分:0)

正如其他人已经提到的那样,this不是您认为的那样。在您的情况下,上下文应传递给计算如下:

totalCredits: ko.computed(function() {
    // Computation goes here..
}, this)

另一种方法可能是在创建对象期间将正确的this存储到某个局部变量(例如var self = this;,然后使用self而不是this)。< / p>

但是,ko.utils.arrayForEach不能使用可观察数组,但适用于纯JavaScript数组,因此您应该打开可观察数组以访问基础数组的元素:

ko.utils.arrayForEach(this.PlannedCourses(), function(course) { 
    // ...
});

// Or

ko.utils.arrayForEach(ko.unwrap(this.PlannedCourses), function(course) { 
    // ... 
});