我正在尝试映射数据,以便在值实际更改时仅重新呈现元素。
{
Apps : [
{
"Categories" : [{
"Name" : "#Some,#More,#Tags,#For,#Measure"
}
],
"Concentrator" : "",
"Health" : 1,
"Id" : 2648,
"Ip" : "1.1.1.1",
"IsDisabled" : true,
"IsObsolete" : false,
"Name" : "",
"Path" : "...",
"SvcUrl" : "http://1.1.1.1",
"TimeStamp" : "\/Date(1463015444163)\/",
"Type" : "...",
"Version" : "1.0.0.0"
}
...
]
...
}
var ViewModel = function() {
self.Apps = ko.observableArray([]);
}
var myModel = new ViewModel();
var map = {
'Apps': {
create: function (options) {
return new AppModel(options.data);
},
key: function(data) { return ko.utils.unwrapObservable(data.Id); }
}
}
var AppModel = function(data){
data.Categories = data.Categories[0].Name.split(',');
ko.mapping.fromJS(data, { }, this);
return this;
}
function UpdateViewModel() {
return api.getDashboard().done(function (data) {
ko.mapping.fromJS(data, map, myModel);
});
}
loopMe(UpdateViewModel, 5000);
function loopMe(func, time) {
//Immediate run, once finished we set a timeout and run loopMe again
func().always(function () {
setTimeout(function () { loopMe(func, time); }, time);
});
}
<script type="tmpl" id="App-template">
<div>
<!-- ko foreach: Categories -->
<span class="btn btn-default btn-xs" data-bind="text:$data"></span>
<!-- /ko -->
</div>
</script>
在第一次运行UpdateViewModel时,我将看到5个预期的跨度。在第二次调用时,接收相同的数据,它会更新为单个跨度,表示[Object object],这是因为它仍然认为Categories是一个对象数组而不是一个字符串数组。
如果我在地图中将“创建”更改为“更新”,那么一切似乎都是固定的,但是无论数据是否发生变化,似乎每次都会重新渲染跨度。
任何人都可以帮助我朝着我需要的方向前进,这样我才能
以下是显示行为的Fiddle
答案 0 :(得分:1)
问题出在这些方面:
var AppModel = function(data){
data.Categories = data.Categories[0].Name.split(','); // <-- mainly this one
ko.mapping.fromJS(data, { }, this);
return this;
}
有两个问题:
你改变data
对象(至少在我们的repro中)会改变data
引用的原始对象。因此,第一次传入一个fakeData对象时,会对其进行一次变异,并且永远会被修复为#34;。
您在AppModel
构造函数函数中对其进行了变异,这只是第一次调用。根据你的key
函数,第二次构造函数应该不被调用,而是ko-mapping应该保留原始对象并将其变异。但它会用错误的&#34;#34;格式化data.Categories
属性。
在我看来,正确的解决方案是在你的数据层中,我们在repro中嘲笑过,所以我的答案向你展示如何做是没有意义的。
另一种更为hacky的方法是在映射中使用update
方法,如下所示:
update: function(options) {
if (!!options.data.Categories[0].Name) {
options.data.Categories = options.data.Categories[0].Name.split(',');
}
return options.data;
},
遇到&#34;未经修改的&#34;数据对象它会做同样的突变。有关该解决方案的实施情况,请参阅this jsfiddle。