淘汰baseEntity属性可用性令人困惑

时间:2013-10-02 14:33:57

标签: javascript inheritance knockout.js durandal

我正在尝试为用户和组等实体实现baseEntity类,但isFavourite属性在{Entity]时无法从Id()读取正确的persistanceId()。 (typeId()出现为未定义且令人惊讶的类型在confirmDelete中具有正确的值

define(["knockout"], function (ko) {
    var app = require('durandal/app');
    ko.baseEntity = function (data) {
        var self = this;
        self.Id = ko.observable();
        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;
        };
        self.persistanceId = function () {
            return self.type + '-' + self.Id() + "-IsFavourite";
        };
        self.isFavourite = ko.observable(false).extend({
            persist: self.persistanceId()
        });
        self.toggleFavourite = function () {
            self.isFavourite(!self.isFavourite());
        };
    }
    return {
        model: ko.baseEntity
    }
});

但是如果isFavourite而不是在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
    }
});

有人可以向我解释这里发生了什么,以及如何将我的基本属性移回我的基础实体中,因为它也会在其他各种事物中共享。

3 个答案:

答案 0 :(得分:2)

我不是javascript master,但我希望将模型层次结构的继承与knockout分离 - 如果你实现了vanilla,模型是否会按预期运行?

答案 1 :(得分:1)

我不遵循为什么你想要修改淘汰对象本身?我相信Dave Lowe建议您仅在JavaScript中执行此操作是正确的。模型上的属性(只要它们影响您的视图)应该是可观察的,但您的模型不需要附加到淘汰赛。

另外,请考虑在http://objectplayground.com花一些时间,这里有一个很好的学习面向对象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中的要求很好,因为你可以做到以下几点:

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

答案 2 :(得分:0)

好吧,显然在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
    }
});

通过这种方式,我设法将我的方法转移到基础并且工作正常。我讨厌回答我自己的问题,所以等待有人添加一些很有价值的答案我可以打勾。