我要做的是从服务器获取数据,然后将其全部放在一个observable中,然后使所有属性都可观察。我面临的问题是它不会使我的所有属性都可观察到,并且我需要它们都是可观察的,因为有时它取决于它使一些属性可观察的数据,有时它不会。
var viewModel = this;
viewModel.Model = ko.observable();
viewModel.SetModel = function (data) {
viewModel.Model(ko.mapping.fromJS(data));
}
我从服务器收到的数据就是这样的例子:normaldata,items(这是一个元素数量未知的数组)。
因此,如果我尝试访问像viewModel.Model().Items[0]().Layer()
这样的数据,我有时会将Layer作为一个函数,有时它是一个带有可观察元素的普通元素。我希望Items中的所有对象都将Layer作为函数。
服务器数据示例: 名称:“测试” 物品:[Layer [ID:132]] 在此示例中,Name,Items和ID是可观察的,但Layer不是。
小提琴示例: jsfiddle.net/98dv11yz/3 所以问题是有时候图层是null,导致ko使属性可观察,但有时该属性有id而ko只使子元素可观察。问题是我在代码中有if,并且我希望它是一个函数,所以我总是可以将它作为layer()进行处理,因为现在它有时是层或层()
答案 0 :(得分:3)
对正在发生的事情的解释:
当ko.mapping
插件遇到输入中的对象时,它会使对象的属性可观察,而不是属性本身。
例如:
var myVM = ko.mapping.fromJS({
name: "Foo",
myObject: {
bar: "Baz"
}
});
归结为:
var myVM = {
name: ko.observable("Foo"),
myObject: {
bar: ko.observable("Baz")
}
}
和不到:
var myVM = {
name: ko.observable("Foo"),
myObject: ko.observable({
bar: ko.observable("Baz")
})
}
您的数据结构存在问题,myObject
有时会null
,有时候会成为对象。在本例中,第一个将被视为name
属性,后者将被视为myObject
道具。
我的建议:
首先:如果您有一个记录良好且统一的数据结构,我建议仅使用ko.mapping.fromJS
方法,而不是具有多个级别和复杂性的大型数据集。有时,创建在其构造函数中具有自己的映射逻辑的slim视图模型更容易。
如果您不希望更改数据结构并希望继续使用ko.mapping
,则必须在客户端更改此部分:
Items: [
{ layer: {id: "0.2"} },
{ layer: null}
]
你必须决定你想要达到的目标。视图模型是否应该使用null
图层去掉项目?或者你想渲染它并能够更新它?以下是在创建视图模型之前如何“更正”数据的示例:
var serverData = {
Name: "Example Name",
Id: "0",
Items: [
{layer: {id: "0.2"} },
{layer: null}
]
};
var correctedData = (function() {
var copy = JSON.parse(JSON.stringify(serverData));
// If you want to be able to render the null item:
copy.Items = copy.Items.map(function(item) {
return item.layer ? item : { layer: { id: "unknown" } };
});
// If you don't want it in there:
copy.Items = copy.Items.filter(function(item) {
return item.layer;
});
return copy;
}());
这种解决方案是否可以接受取决于您的实际使用情况会变得多么复杂。如果数据的复杂性和交互性更高,我建议将项目映射到他们自己的视图模型,这些视图模型处理缺少的属性,而不是... ...