ko.mapping.fromJS 值设置为 null 后不映射嵌套值

ko.mapping.fromJS not mapping nested value after value is set null

我正在使用 ko.mapping.fromJS 将 JSON 数据应用到我的 ViewModel。此 JSON 数据中包含嵌套对象,如下所示:

var data = {
   item : "#1234",
   description: "This is item #1",
   moreinfo: {
       condition: "Good"
   }
}

当我尝试将新数据重新映射到对象时,它工作正常,更新了所有值。但是,如果我将 moreinfo 的值重新映射到 null,因为此项目没有更多信息,如下所示:

var data2 = {
   item : "#4567",
   description: "This is item #2",
   moreinfo:null
}

它不会更新 DOM,而是保留以前的值 condition:"Good"。如果我再将值更新一次为具有 moreinfo 的数据,如下所示:

var data3 = {
   item : "#7890",
   description: "This is item #3",
   moreinfo: {
       condition: "Bad"
   }
}

它仍然会更新项目和描述,但不会更新 DOM 而是保留值 condition:"Good"

我是不是使用了不正确的映射,还是您可以不让值变成 null

Javascript:

var viewModel;
$("#button1").on("click", function(){
   viewModel = ko.mapping.fromJS(data);
   ko.applyBindings(viewModel, $("itemWrapper")[0]);
});
$("#button2").on("click", function(){
  ko.mapping.fromJS(data2, {}, viewModel);
});
$("#button3").on("click", function(){
  ko.mapping.fromJS(data3, {}, viewModel);
});

HTML:

<div id="itemWrapper">
    <p data-bind="text: item"></p>
    <p data-bind="text: description"></p>
    <p data-bind="text: moreinfo.condition"></p>
</div>

<button id="button1">
Bind Data #1
</button>
<button id="button2">
Bind Data #2
</button>
<button id="button3">
Bind Data #3
</button>

JSfiddle:https://jsfiddle.net/hrgx5f1y/

Knockout 绑定处理程序的工作方式是它们连接到一个可观察对象,并在该可观察对象发生变化时做出响应。它不绑定到你的绑定表达式,而是绑定到你的可观察对象 所以你的绑定:

<p data-bind="text: moreinfo.condition"></p>

...获取 moreinfocondition 属性,这是一个可观察对象并订阅它。当你这样做时:

 var data4 = {
   item : "#0000",
   description: "This is item #4",
   moreinfo: {
       condition: "Meh"
   }
 }
 ko.mapping.fromJS(data4, {}, viewModel);

...之所以有效,是因为 Knockout 可以将 data4 的结构绑定到您的视图模型,并使用新值 'Meh'.

更新完全相同的可观察对象

如果改为这样做:

var data2 = {
  item : "#4567",
  description: "This is item #2",
  moreinfo:null
}
$("#button2").on("click", function(){
  ko.mapping.fromJS(data2, {}, viewModel);
});

...它不是在更新那个可观察的,而是在更新 moreinfo 属性 所以它是空的。由于绑定是针对可观察对象,而不是 expression,即使您更新视图模型使 moreinfo 不再为 null,也不会重新评估绑定表达式;您的 DOM 仍然绑定到相同的原始可观察对象。

您可以通过将 moreinfo 作为一个可观察对象,绑定到它,然后再绑定到 condition 来解决这个问题;这样,如果任一更新,您的 DOM 将按预期更新。例如:

<!-- ko with:moreinfo -->
  <p data-bind="text: condition"></p> 
<!-- /ko -->