我使用Knockout和ko.mapping插件来创建和更新我的viewmodel。我有一个像服务器这样的json结构,例如:
var viewmodel = {
name: "Foo",
person: {
forename: "John",
surname: "Smith"
}
};
当我使用ko.mapping.fromJS(viewmodel)
创建我的viewmodel时,只有叶节点被转换为observables,所以我得到类似于以下内容的东西:
var viewmodel = {
name: ko.observable("Foo"),
person: {
forename: ko.observable("John"),
surname: ko.observable("Smith")
}
};
但是我需要每个属性都是一个可观察的(在这个例子中person
也必须是一个obervable)因为我有一些可以处理复杂的可观察对象的自定义绑定。
如何配置映射插件以将每个属性转换为可观察的?
我知道我可以使用这样的东西:
var mapping = {
'person': {
create: function (options) {
var myPersonData = ko.mapping.fromJS(options.data);
return ko.observable(myPersonData);
}
}
};
ko.mapping.fromJS(viewmodel, mapping);
但我需要一个动态的解决方案,因为我不知道属性名称(例如" person")。服务器生成一个动态json对象并将其返回给客户端(带有绑定的HTML代码也是使用正确的属性名称动态创建的)。 必须对json对象中的每个属性执行上面显示的函数 - 这可能吗?或者有替代解决方案吗?
答案 0 :(得分:1)
我并不完全相信这是多么合理,但作为一个粗略的解决方案,它似乎做了你想做的事。
基本上,遍历javascript数据对象上的所有属性,检查它们是否属于您的属性(使用hasOwnProperty())。然后,您需要查看属性的类型,如果它是一个对象,则需要递归调用makeObservable方法,否则将该属性创建为observable。
我没有实现所有类型,只有字符串,数组和对象,所以你需要填写其余类型:
function makeObservable(data, viewmodel) {
var vm = viewmodel || ko.observable({});
for (var prop in data) {
if (data.hasOwnProperty(prop)) {
var ctorType = data[prop].constructor;
var mappedProperty;
if (ctorType === String) {
mappedProperty = ko.observable(data[prop]);
} else if (ctorType === Array) {
mappedProperty = ko.observableArray();
for (var arr in data[prop]) {
if (data[prop].hasOwnProperty(arr)) {
mappedProperty.push(makeObservable(data[prop][arr]));
}
}
} else if (ctorType === Object) {
mappedProperty = makeObservable(data[prop]);
}
if (ko.isObservable(vm)) {
vm()[prop] = mappedProperty;
} else {
vm[prop] = mappedProperty;
}
}
}
return vm;
}
var viewModel = makeObservable(data, {});
我还创建了一个jsFiddle