Knockout继承重用基础ViewModel的相同实例?

时间:2016-11-28 17:26:49

标签: asp.net-mvc knockout.js

我在MVC应用程序上使用Knockout.js。 我试图使用继承,但我认为可以重用BaseViewModel,而不是为每个ViewModel实例创建一个新的。

我有一个BaseViewModel,以及多个扩展它的ViewModel。所有Views \ ViewModels的行为都相同 - 它们将项目列表显示为html表格,单击行的编辑按钮会弹出模态窗口中的选定行,以便您可以编辑并保存对该项目的更改行。

这些都适用于他们的独立观点。但是,当我尝试在一个视图上显示它们时,我遇到了问题。

每个视图的列表都绑定得很好。 单击最后列表/表的选定行上的编辑工作正常。 但是,单击FIRST列表/表的选定行上的编辑会失败并显示错误。

Uncaught ReferenceError: Unable to process binding "value: function (){return Name }"

"名称"是第二个ViewModel上模型的属性,而不是第一个。

似乎错误是因为只创建了一个BaseViewModel,因此每次向View添加新的ViewModel时都会覆盖该BaseViewModel的属性。

这是一个问题示例的小提琴。 JSFiddle

查看editItem函数并调出控制台。 然后单击第二个表的编辑,您将看到它正确打印到控制台传递给基类的值,并且模态窗口打开正常。

如果您随后取消并单击第一个表的编辑,您将看到它打印第二个ViewModel传递到BaseVM的SAME值,而不是它自己传入的值。

这是我的淘汰赛BaseViewModel以及派生的ViewModel。

EnvironmentAssetBaseViewModel = function(modalWindowName, apiResourceName, modelDefinition) {
    var self = this;
    self.modalWindowName = modalWindowName;
    self.apiResourceName = apiResourceName;
    self.modelDefinition = modelDefinition;
    self.itemList = ko.observableArray([]);
    self.selectedRow = ko.observable(modelDefinition);

    function getData() {
        //make ajax API call and store data in itemList
        var data = [];
        if (apiResourceName == 'activityLogs') {
            data = [
                { Id: "1", Action: "a", Details: "d"}, 
                { Id: "2", Action: "b", Details: "e"}, 
                { Id: "3", Action: "c", Details: "f"}
            ]
        } else {
            data = [
                { Id: "109", Name: "a", Description: "d" }, 
                { Id: "209", Name: "b", Description: "e" }, 
                { Id: "309", Name: "c", Description: "f" }
            ]
        }

        self.itemList(data);
    }

    function editItem(item) {
        console.log(self.modalWindowName);
        console.log(self.apiResourceName);
        console.log(self.modelDefinition);
        self.selectedRow(item);
        $(modalWindowName).modal('show');
    }

    function cancel(item) {
        $(modalWindowName).modal('hide');
    }
    return {
        self: self,
        itemList: self.itemList,
        selectedRow: self.selectedRow,
        getData: getData,
        editItem: editItem,
        cancel: cancel
    }
};



ActivityLogsViewModel = function() {
    var self = this;
    var modalName = "#activityLogModal";
    var apiResourcename = "activityLogs";
    var modelDefinition = { Id: "", Action: "", Details: "" };

    ko.utils.extend(self, new EnvironmentAssetBaseViewModel(modalName, apiResourcename, modelDefinition));
    getData(); //initial data load

    return {
        self: self,
        editItem: editItem,
        cancel: cancel
    }
};
ko.applyBindings(ActivityLogsViewModel, document.getElementById('activityLogsDiv'));




DomainsViewModel = function() {
  var self = this;
  var modalName = "#domainModal";
  var apiResourcename = "domains";
  var modelDefinition = { Id: "", Name: "", Description: "" };

  ko.utils.extend(self, new EnvironmentAssetBaseViewModel(modalName, apiResourcename, modelDefinition));
  getData(); //initial data load

  return {
    self: self,
    editItem: editItem,
    cancel: cancel
  }
};


ko.applyBindings(DomainsViewModel, document.getElementById('domainsDiv'));

1 个答案:

答案 0 :(得分:0)

您正在混淆一些创建函数“实例”的方法。

您已经定义了“手动”返回普通对象的构造函数。这非常好,但这意味着您不能使用new关键字调用它们。

new关键字会创建一个新的this上下文,但由于您没有使用它,您的第一行:

var self = this;

会将self设置为工厂方法调用者的上下文。在这种情况下,window

这意味着所有构造函数/工厂都在污染window命名空间,从而导致缺少/覆盖的奇怪属性组合。

尝试用var self = this替换var self = {}以创建新对象。确保调用函数来创建视图模型:var activityVM = ActivityLogsViewModel()

你会遇到其他一些错误(例如,getData()需要self.getData()),但你应该能够弄明白。

如果您需要更多帮助,请与我联系。