Javascript 敲除映射创建/更新有问题
我正在尝试映射数据,以便仅当值实际发生更改时才重新渲染元素Javascript 敲除映射创建/更新有问题,javascript,knockout.js,knockout-mapping-plugin,Javascript,Knockout.js,Knockout Mapping Plugin,我正在尝试映射数据,以便仅当值实际发生更改时才重新渲染元素 { Apps : [ { "Categories" : [{ "Name" : "#Some,#More,#Tags,#For,#Measure" } ], "Concentrator" : "", "Health" : 1,
{
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>
{
应用程序:[
{
“类别”:[{
“名称”:“#一些,#更多,#标记,#用于,#度量”
}
],
“集中器”:“,
"健康":一,,
“Id”:2648,
“Ip”:“1.1.1.1”,
“IsDisabled”:正确,
“Isobsolite”:假,
“名称”:“,
“路径”:“…”,
“SvcUrl”:”http://1.1.1.1",
“时间戳”:“\/日期(1463015444163)\/”,
“类型”:“…”,
“版本”:“1.0.0.0”
}
...
]
...
}
var ViewModel=函数(){
self.Apps=ko.observearray([]);
}
var myModel=new ViewModel();
变量映射={
“应用程序”:{
创建:函数(选项){
返回新的AppModel(options.data);
},
键:函数(数据){return ko.utils.unwrapobbservable(data.Id);}
}
}
var AppModel=函数(数据){
data.Categories=data.Categories[0].Name.split(',');
fromJS(数据,{},this);
归还这个;
}
函数UpdateViewModel(){
返回api.getDashboard().done(函数(数据){
fromJS(数据、地图、myModel);
});
}
loopMe(UpdateViewModel,5000);
函数loopMe(函数,时间){
//立即运行,完成后,我们设置超时并再次运行loopMe
func().始终(函数(){
setTimeout(函数(){loopMe(func,time);},time);
});
}
在UpdateViewModel的第一次运行中,我将看到预期的5个跨度。在第二次调用中,接收到相同的数据,它被更新为一个称为[Object Object]的范围,这是因为它仍然认为类别是一个对象数组,而不是字符串数组
如果我将地图中的“创建”更改为“更新”,一切似乎都已修复,但似乎每次都会重新渲染跨距,而不管数据是否更改
谁能帮我一把,让我朝着我要去的方向走
下面是一个显示行为的示例问题在于这些行:
var AppModel = function(data){
data.Categories = data.Categories[0].Name.split(','); // <-- mainly this one
ko.mapping.fromJS(data, { }, this);
return this;
}
当它遇到一个“未修改”的数据对象时,它将执行相同的变异。请参阅,以了解实际的解决方案。我想提供帮助,所以我从开始,但发现JSFIDLE根本没有显示任何问题?(没有“[对象]”麻烦,没有重新渲染类别,什么都没有。)你能解释一下我的复制哪里出错了,或者把你的代码更新成mcve吗?@Jeroen谢谢你帮我做了一把小提琴。我已经编辑了你开始的地方,并复制了我看到的行为。我添加了一个计数器,可以切换伪造的数据,但是数据是一样的。谢谢你帮我找到了。我知道我把地图弄错了。我想我只是没有把2和2放在一起。谢谢你抽出时间。我将按照您的建议,通过数据层解决这个问题。
update: function(options) {
if (!!options.data.Categories[0].Name) {
options.data.Categories = options.data.Categories[0].Name.split(',');
}
return options.data;
},