Javascript 敲除baseEntity属性的可用性令人困惑

Javascript 敲除baseEntity属性的可用性令人困惑,javascript,inheritance,knockout.js,durandal,Javascript,Inheritance,Knockout.js,Durandal,我正在尝试为用户和组等实体实现baseEntity类,但当属性位于baseEntity中时,isFavorite属性无法从persistanceId()读取正确的Id()。(type和Id()显示为未定义,令人惊讶的是,type在confirmDelete中具有正确的值) 但如果isfavorite不是在baseEntity中,而是例如组的一部分,那么它工作正常 define(["knockout", "models/baseentity"], function (ko, baseEntity)

我正在尝试为用户和组等实体实现baseEntity类,但当属性位于baseEntity中时,
isFavorite
属性无法从
persistanceId()
读取正确的
Id()。(
type
Id()
显示为未定义,令人惊讶的是,type在
confirmDelete
中具有正确的值)

但如果
isfavorite
不是在baseEntity中,而是例如组的一部分,那么它工作正常

define(["knockout", "models/baseentity"], function (ko, baseEntity) {
    var
    model = function (data) {
        var self = this;
        baseEntity.model.call(self);
        self.type = 'group';
        self.Id(data.Id);
        self.Name = ko.observable(data.Name);
        self.Description = ko.observable(data.Description);
        self.Members = ko.observableArray(data.Members);
        self.isFavourite = ko.observable(false).extend({
            persist: self.persistanceId()
        });
    }
    return {
        model: model
    }
});

有人能给我解释一下这里发生了什么,以及我如何将我的基本属性移回我的baseentity中,因为它也在各种其他事物中共享。

我不是javascript大师,但我希望将模型层次结构的继承与敲除分离开来-如果实现它,模型的行为是否符合预期?

I我不是javascript大师,但我希望将模型层次结构的继承与敲除分离开来——如果实现它,模型的行为是否符合预期?

好的,显然在ko中做这个子类业务更容易的方法是使用ko本身。谁会想到:)

现在我将我的基本模型定义为:

define(["knockout"], function (ko) {
    var app = require('durandal/app');
    ko.baseEntity = function (type, data) {
        var self = this;
        self.Id = ko.observable(data.Id);
        self.Type = ko.observable(type);
        self.Name = ko.observable();
        self.persistanceId = ko.computed(function () {
            return self.Type() + '-' + self.Id() + "-IsFavourite";
        });
        self.isFavourite = ko.observable(false).extend({
            persist: self.persistanceId()
        });
        self.toggleFavourite = function () {
            self.isFavourite(!self.isFavourite());
        };
        self.confirmDelete = function () {
            var result;
            app.showMessage('Are you sure you want to delete the ' + self.Type() + ' ' + self.Name() + '?', 'Deleting ' + self.Type(), ['Yes', 'No'])
                .then(function (dialogResult) {
                    dialogResult === "Yes" ? result = true : result = false;
                });
            return result;
        };
    }
    return {
        model: ko.baseEntity
    }
});
正如您所看到的,我现在已经添加了我传递到具体实现中的相同数据参数。这是可能的,因为稍后我将使用
ko.utils.extend
创建此实例并对其进行扩展:

define(["knockout", "models/baseentity", "config"], function (ko, baseEntity, config) {
    var
    model = function (data) {
        var self = this;
        ko.utils.extend(self, new baseEntity.model(config.subClassTypes.user, data));
        self.Id(data.Id);
        self.FirstName = ko.observable(data.FirstName);
        self.LastName = ko.observable(data.LastName);
        self.JobTitle = ko.observable(data.JobTitle);
        self.UserLevel = ko.observable(data.UserLevel);
        self.Groups = ko.observableArray(data.Groups);
        self.ImageUrl = data.ImageUrl;
        self.Name(self.FirstName() + ' ' + self.LastName());
    }
    return {
        model: model
    }
});
另一个子类示例:

define(["knockout", "models/baseentity", "config"], function (ko, baseEntity, config) {
    var
    model = function (data) {
        var self = this;
        ko.utils.extend(self, new baseEntity.model(config.subClassTypes.group, data));
        self.Id(data.Id);
        self.Name(data.Name);
        self.Description = ko.observable(data.Description);
        self.Members = ko.observableArray(data.Members);       
    }
    return {
        model: model
    }
});

通过这种方式,我成功地将我的方法转移到了基地,效果很好。我讨厌回答我自己的问题,所以等着别人给我添加一些有价值的答案,我可以打勾

好的,显然在ko中做这个子类业务更简单的方法是使用ko本身。谁会想到:)

现在我将我的基本模型定义为:

define(["knockout"], function (ko) {
    var app = require('durandal/app');
    ko.baseEntity = function (type, data) {
        var self = this;
        self.Id = ko.observable(data.Id);
        self.Type = ko.observable(type);
        self.Name = ko.observable();
        self.persistanceId = ko.computed(function () {
            return self.Type() + '-' + self.Id() + "-IsFavourite";
        });
        self.isFavourite = ko.observable(false).extend({
            persist: self.persistanceId()
        });
        self.toggleFavourite = function () {
            self.isFavourite(!self.isFavourite());
        };
        self.confirmDelete = function () {
            var result;
            app.showMessage('Are you sure you want to delete the ' + self.Type() + ' ' + self.Name() + '?', 'Deleting ' + self.Type(), ['Yes', 'No'])
                .then(function (dialogResult) {
                    dialogResult === "Yes" ? result = true : result = false;
                });
            return result;
        };
    }
    return {
        model: ko.baseEntity
    }
});
正如您所看到的,我现在已经添加了我传递到具体实现中的相同数据参数。这是可能的,因为稍后我将使用
ko.utils.extend
创建此实例并对其进行扩展:

define(["knockout", "models/baseentity", "config"], function (ko, baseEntity, config) {
    var
    model = function (data) {
        var self = this;
        ko.utils.extend(self, new baseEntity.model(config.subClassTypes.user, data));
        self.Id(data.Id);
        self.FirstName = ko.observable(data.FirstName);
        self.LastName = ko.observable(data.LastName);
        self.JobTitle = ko.observable(data.JobTitle);
        self.UserLevel = ko.observable(data.UserLevel);
        self.Groups = ko.observableArray(data.Groups);
        self.ImageUrl = data.ImageUrl;
        self.Name(self.FirstName() + ' ' + self.LastName());
    }
    return {
        model: model
    }
});
另一个子类示例:

define(["knockout", "models/baseentity", "config"], function (ko, baseEntity, config) {
    var
    model = function (data) {
        var self = this;
        ko.utils.extend(self, new baseEntity.model(config.subClassTypes.group, data));
        self.Id(data.Id);
        self.Name(data.Name);
        self.Description = ko.observable(data.Description);
        self.Members = ko.observableArray(data.Members);       
    }
    return {
        model: model
    }
});

通过这种方式,我成功地将我的方法转移到了基地,效果很好。我讨厌回答我自己的问题,所以等着别人给我添加一些有价值的答案,我可以打勾

我不明白为什么要修改敲除对象本身?我相信Dave Lowe建议您单独使用JavaScript来实现这一点是正确的。模型上的属性(在一定程度上影响视图)应该是可观察的,但模型不需要附加到敲除

也可以考虑花些时间,这对学习面向对象的JavaScript有很好的指导作用。您的范例应该更像这样:

function Model(obj) {

    this.attribute = obj.attribute;

    this.observable = ko.observable(obj.observable);

    this.localFunction = function(val) {
        if (obj.attr == true) this.observable(val);
    };
}

Model.prototype.globalFunction = function(data) {
    this.observable(data);
};
请特别注意,如果方法依赖于局部变量,即传递给构造函数的参数,则需要在构造函数中定义它。否则,您应该在原型上定义方法

此范例在durandal中与require配合使用效果非常好,因为您可以执行以下操作:

define(function(require) {
    var Model = require('model');
    var object = new Model({});
})

我不明白为什么要修改敲除对象本身?我相信Dave Lowe建议您单独使用JavaScript来实现这一点是正确的。模型上的属性(在一定程度上影响视图)应该是可观察的,但模型不需要附加到敲除

也可以考虑花些时间,这对学习面向对象的JavaScript有很好的指导作用。您的范例应该更像这样:

function Model(obj) {

    this.attribute = obj.attribute;

    this.observable = ko.observable(obj.observable);

    this.localFunction = function(val) {
        if (obj.attr == true) this.observable(val);
    };
}

Model.prototype.globalFunction = function(data) {
    this.observable(data);
};
请特别注意,如果方法依赖于局部变量,即传递给构造函数的参数,则需要在构造函数中定义它。否则,您应该在原型上定义方法

此范例在durandal中与require配合使用效果非常好,因为您可以执行以下操作:

define(function(require) {
    var Model = require('model');
    var object = new Model({});
})

是的,我知道ko.baseEntity是愚蠢的,但仍然必须保留一些基本模型道具作为淘汰道具,因为它们主要用于视图的数据绑定。谢谢你的帮助是的,绝对可行。如果您将属性a设置为模型上的ko.observable,然后创建一个SpecialModel构造函数并设置SpecialModel.prototype=new Model(),SpecialModel将有一个可观察属性a,您可以在构造函数中调用类似的东西。a('abc')。是的,我知道ko.baseEntity很愚蠢,但仍然必须保留一些基本模型道具作为淘汰道具,因为它们主要用于视图的数据绑定。谢谢你的帮助是的,绝对可行。如果将属性a设置为模型上的ko.observable,然后创建一个SpecialModel构造函数并设置SpecialModel.prototype=new Model(),则SpecialModel将具有一个可观察属性a,您可以在构造函数中调用类似的.a('abc')。