您的代码存在各种问题,但不会因为映射插件使用不当而引发错误。
范围问题
首先,fullAddress 是 Address 实例的属性,因此您应该在其前面加上 address. 第二,with 绑定告诉 Knockout 查找不存在的 editingPerson.savePerson。因此,您必须将绑定更改为根范围,如下所示:click: $root.savePerson。
<!-- current --> inputAddress: <input data-bind="value: fullAddress">
<!-- correct --> inputAddress: <input data-bind="value: address.fullAddress">
<!--current --> <button data-bind="click:savePerson" type="button">Save</button>
<!--correct --> <button data-bind="click:$root.savePerson" type="button">Save</button>
还建议使用对象作为构造函数参数,以便更轻松地与mapping plugin 结合使用,如果您希望省略一个属性。
映射插件
映射插件文档明确指出:
对象的所有属性都被转换为可观察对象。
这意味着你不能包含 computed observables 并期望它们正常工作。事实上,文档中有一部分是关于用计算的 observables 扩充 JS 对象here。我可能错了,但从我的测试和文档来看,create 映射函数似乎不能用于嵌套对象。按照本文档,您无需显式创建所有可观察属性,因为对 ko.mapping.fromJS 的单个调用可以实例化它们。您的新 Person 构造函数将如下所示:
function Person(options){
// because these arrays contain nested objects with computed observables,
// they should have a special create function
var self = this, mapping = {
'amounts': { create: function(options) { return new Amount(options.data); }},
'address': { create: function(options) { return new Address(options.data); }}
};
// instantiates all properties, eg. surname, name, id
ko.mapping.fromJS(options, mapping, this);
self.fullName = ko.computed(function() {
return self.name()+" - "+self.surname();
});
}
另一个次要的“挑剔”:您只能在命名对象属性上使用映射插件的 create 函数,因此在您原来的小提琴中,插件将永远找不到 persons 数组,因为它是数据根。
查看this fiddle 以获得完整的解决方案。