我在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'));
答案 0 :(得分:0)
您正在混淆一些创建函数“实例”的方法。
您已经定义了“手动”返回普通对象的构造函数。这非常好,但这意味着您不能使用new
关键字调用它们。
new
关键字会创建一个新的this
上下文,但由于您没有使用它,您的第一行:
var self = this;
会将self
设置为工厂方法调用者的上下文。在这种情况下,window
。
这意味着所有构造函数/工厂都在污染window
命名空间,从而导致缺少/覆盖的奇怪属性组合。
尝试用var self = this
替换var self = {}
以创建新对象。确保调用函数来创建视图模型:var activityVM = ActivityLogsViewModel()
。
你会遇到其他一些错误(例如,getData()
需要self.getData()
),但你应该能够弄明白。
如果您需要更多帮助,请与我联系。