Knockout.js 敲除-JavaScript运行时错误:对象不';t支持属性或方法';级别';

Knockout.js 敲除-JavaScript运行时错误:对象不';t支持属性或方法';级别';,knockout.js,knockout-2.0,knockout-mapping-plugin,Knockout.js,Knockout 2.0,Knockout Mapping Plugin,我很难理解为什么这个简单的测试会抛出运行时错误 作为FilterClause对象的一部分,我已经获得了一个敲除计算属性“Level”,我完全遵循了文档,但它仍然抛出运行时错误 JavaScript runtime error: Object doesn't support property or method 'Level' 我认为这与在声明computed属性函数的构造时没有实例化的对象有关。但它紧随其后,或者至少似乎完全遵循了淘汰文档 困惑 这是我的密码: var FilterClause

我很难理解为什么这个简单的测试会抛出运行时错误

作为FilterClause对象的一部分,我已经获得了一个敲除计算属性“Level”,我完全遵循了文档,但它仍然抛出运行时错误

JavaScript runtime error: Object doesn't support property or method 'Level'
我认为这与在声明computed属性函数的构造时没有实例化的对象有关。但它紧随其后,或者至少似乎完全遵循了淘汰文档

困惑

这是我的密码:

var FilterClause = function (json, parent) {
    this.FilterClauseID = ko.observable();
    this.Type = ko.observable();
    this.Left = ko.observable();
    this.Right = ko.observable();
    this.ParentID = ko.observable();
    this.Parent = ko.observable(parent);
    this.Children = ko.observableArray();
    this.Level = ko.observable(0);

    // computed
    this.Padding = ko.computed(function () {
        return this.Level().ToString() + "px";
    });

    var mapping = {
        'Children': {
            create: function (args) {
                return new FilterClause(args.data, this);
            }
        },
        'ignore': ["Parent"]
    };

    ko.mapping.fromJS(json, mapping, this);
}

您对计算内部的上下文有问题。有两种方法可以修复错误。第一个是将其作为第二个参数添加到计算:

this.Padding = ko.computed(function () {
    return this.Level().ToString() + "px";
}, this);
工作小提琴:

或第二个-将其分配给变量:

var self = this;
self.FilterClauseID = ko.observable();
self.Type = ko.observable();
self.Left = ko.observable();
self.Right = ko.observable();
self.ParentID = ko.observable();
self.Parent = ko.observable(parent);
self.Children = ko.observableArray();
self.Level = ko.observable(0);

// computed
self.Padding = ko.computed(function () {
    return self.Level().toString() + "px";
})
工作小提琴:


仔细阅读这篇文章。它详细解释了问题的根本原因。

在计算填充中,这指的是窗口

为了避免这种情况,您应该创建一个自私有字段:

var self = this;
self.FilterClauseID = ko.observable();
self.Type = ko.observable();
self.Left = ko.observable();
self.Right = ko.observable();
self.ParentID = ko.observable();
self.Parent = ko.observable(parent);
self.Children = ko.observableArray();
self.Level = ko.observable(0);

// computed
this.Padding = ko.computed(function () {
    return self.Level().toString() + "px";
});

好极了!!我现在明白了。非常感谢你。我的错是没有完全阅读文档。那么,对于一个经验丰富的knockout/javascript程序员来说,两个工作示例中哪一个更可取?示例“一”看起来更整洁,但示例“二”更清晰,但可能更容易出错。我猜是个人选择?另一个问题@Artem Vyshniakov,如果父母的“级别”值也处于构建状态,你会如何从父母那里获得?我更喜欢第二种方式。抱歉,没有回答您的问题。抱歉@Artem Vyshniakov,没有很好地解释我自己,请看您更新的小提琴,基本上我正在尝试从父项获取并使用一个值。将父项存储在vm中并不是最好的解决方案。您可以在视图中使用现有的$parent对象,而不是将其添加到vm中。阅读这篇文章-