Knockout全新,我正在尝试使用knockout映射插件将JSON响应从服务器映射到特定模型。模型是嵌套的,我试图使用create
回调覆盖对象构造,即使在嵌套模型中也是如此。但是,似乎没有正确读取我的映射选项。示例JSON:
{
"EmployeeFeedbackRequestSubmissions": [
{
"EmployeeFeedbackRequestSubmissionId": 0,
"Employee": "John Smith0",
"EmployeesWorkedWith": [
{
"EmployeeName": "Joe Smith",
"ProjectsWorked": [
{
"ProjectName": "Document Management Console"
},
{
"ProjectName": "Performance Eval Automation"
},
{
"ProjectName": "Business Tax Extensions"
}
]
},
{
"EmployeeName": "Michael Jones",
"ProjectsWorked": [
{
"ProjectName": "Document Management Console"
},
{
"ProjectName": "Performance Eval Automation"
},
{
"ProjectName": "Business Tax Extensions"
}
]
},
{
"EmployeeName": "Jason Smith",
"ProjectsWorked": [
{
"ProjectName": "Document Management Console"
},
{
"ProjectName": "Performance Eval Automation"
},
{
"ProjectName": "Business Tax Extensions"
}
]
},
{
"EmployeeName": "Robert Will",
"ProjectsWorked": [
{
"ProjectName": "Document Management Console"
},
{
"ProjectName": "Performance Eval Automation"
},
{
"ProjectName": "Business Tax Extensions"
}
]
}
]
}
// more EmployeeFeedbackRequestSubmissions
]
}
映射选项:
var mappingOptions = {
// overriding default creation/initialization code
'EmployeeFeedbackRequestSubmissions': {
create: function (options) {
return (new(function () {
this.EmployeeHeading = ko.computed(function () {
return "Performance Evaluation Employee: " + this.Employee();
}, this);
ko.mapping.fromJS(options.data, {}, this);
})());
},
'EmployeesWorkedWith': {
create: function (options) {
return new instance.EmployeesWorkedWithModel(options.data);
}
}
}
};
示例小提琴完整示例:http://jsfiddle.net/jeades/9ejJq/2/
结果应该是能够使用nameUpper
中的计算EmployeesWorkedWithModel
。我也愿意接受有关更好方法的建议,因为这可能不是处理此问题的最佳方式。
答案 0 :(得分:2)
你快到了。直接工作:http://jsfiddle.net/jiggle/na93A/
映射选项对象不需要嵌套,当您将映射插件传递给ko.mapping.fromJSON时,映射插件将从名称中查找映射
所以你的映射选项对象应该是单级的:
var self = this;
self.mappingOptions = {
// overriding default creation/initialization code
'EmployeeFeedbackRequestSubmissions': {
create: function (options) {
return (new(function () {
this.EmployeeHeading = ko.computed(function () {
return "Performance Evaluation Employee: " + this.Employee();
}, this);
ko.mapping.fromJS(options.data, self.mappingOptions, this);
})());
}
},
'EmployeesWorkedWith': {
create: function (options) {
// return new instance.EmployeesWorkedWithModel(options);
return (new(function(){
ko.mapping.fromJS(options.data, {}, this);
this.nameUpper = ko.computed(function () {
return this.EmployeeName().toUpperCase();
}, this);
})());
}
}
};
注意我使用“self”作为本地引用'this'而不是'instance',只是为了使代码更容易阅读(就像在主视图模型中使用'instance')。
我还将mappingOptions对象作为FeedbackViewModel的一部分,因为我们需要将它传递给mapping.fromJS调用,所以当它看到数据中的'EmployeesWorkedWith'级别时,它将为它提供mappingOptions。
自:
ko.mapping.fromJS(options.data, {}, this);
要:
ko.mapping.fromJS(options.data, self.mappingOptions, this);
然后,您可以将“EmployeesWorkedWith”级别的创建代码移动到create中(您可以调用函数,但我已将它保存在mappingOptions中,如上所示,就像您创建'EmployeeFeedbackRequestSubmissions'级别一样
然后你可以完全摆脱instance.EmployeesWorkedWithModel函数。
可以在这里找到一个工作小提琴:
http://jsfiddle.net/jiggle/na93A/
或者,您可以在创建“EmployeeFeedbackRequestSubmissions”时创建单独的mappingOptions对象,而不是在一个对象中具有所有级别的映射,这可以在这个小提琴中看到http://jsfiddle.net/jiggle/Avam7/
取决于您喜欢哪种编码风格,如果您对不同级别有不同的映射需求并且它们具有相同的集合名称,则将它们分开是很重要的。
例如
员工
员工
员工(您可能需要在此级别使用不同的计算机等)
如果是这样,您将使用第二个选项(将mappingOptions分开并传递给将使用它的级别)
我已经向fiddles添加了一些console.log语句,因此您可以在控制台中运行代码时看到值,这将有助于了解它是如何工作的。
希望它有所帮助。
答案 1 :(得分:1)
ko.mapping的好处在于流程的自动化程度。 在http://jsfiddle.net/9ejJq/26/
中查看结果您将注意到我们如何仅使用一个声明的映射来解决问题。
feedbackMappingOptions = {
create: function (options) {
return new FeedbackViewModel(options.data);
}
};
从那时起,每个视图模型都会触发其子对象的映射。您可以为每个创建一个映射选项,或者如您在EmployeesWorkedWith下看到的最终ProjectsWorked对象,我们只是将数据放在映射中,ko.mapping完成剩下的工作。希望这有帮助。