我稍微改变了你的代码。检查此版本的JSFiddle。
var jsonFromServer = '{"ModuleId":1,"Metadatas":[{"Id":1,"MinValue":null,"MaxValue":null,"FieldName":"Teste","SelectedType":"String","SelectedOptionType":null,"IsRequired":true,"Options":[]}]}';
您的代码不起作用,因为您的 jsonFromServer 变量不包含我们在绑定时需要的方法,就像您在问题中描述的那样。(--> 元数据)
所以我们需要在映射过程中为 Metadata 对象定义一个自定义创建函数,如下所示:
var mapping = {
'Metadatas': {
create: function(options) {
var newMetaData = new MetadataViewModel(options.parent);
newMetaData.Id(options.data.id);
newMetaData.FieldName(options.data.FieldName);
newMetaData.SelectedType(options.data.SelectedType);
newMetaData.SelectedOptionType(options.data.SelectedOptionType);
newMetaData.IsRequired(options.data.IsRequired);
newMetaData.Options(options.data.Options);
// You can get current viewModel instance via options.parent
// console.log(options.parent);
return newMetaData;
}
}
}
然后我将您的加载功能更改为:
self.LoadDataFromServer = function() {
var jsonFromServer = '{"ModuleId":1,"Metadatas":[{"Id":1,"MinValue":null,"MaxValue":null,"FieldName":"Teste","SelectedType":"String","SelectedOptionType":null,"IsRequired":true,"Options":[]}]}';
ko.mapping.fromJSON(jsonFromServer, mapping, self);
}
您不必声明新的 viewModel 并再次调用 ko.applyBindings。将更新后的映射分配给当前 viewModel 就足够了。有关更多信息,请查看此链接。注意自定义对象构造部分。
最后一个问题是:在不使加载过程过于繁琐的情况下,将项目放在最终数组中的最佳方法是什么,例如遍历每个项目并填充项目的属性以保留先前声明的方法?
据我所知,没有简单的方法可以通过您的对象实现来做到这一点。你的对象并不简单。它们同时包含数据和函数。因此,您需要为它们定义自定义创建功能。但是,如果您能够像下面这样将其分开,那么您不必自定义对象构造。
例如,将 MetadataViewModel 分离到两个不同的对象:
--> Metadata : which contains only simple data
--> MetadataViewModel : which contains Metadata observableArray and its Metadata manipulator functions
使用此结构,您可以调用 ko.mapping.fromJSON(newMetaDataArray , {} , MetadataViewModelInstance.MetadataArray) 而无需在映射过程中定义自定义创建函数。