【问题标题】:ko.mapping.fromJS not mapping nested value after value is set nullko.mapping.fromJS 在值设置为 null 后不映射嵌套值
【发布时间】:2017-01-28 12:53:16
【问题描述】:

我正在使用 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/

  • 如果您使用 Button #1 applyBindings,然后使用 #2 映射 null,然后使用 #3 映射新值,您将看到我描述的问题。

  • 如果您使用 Button #1 applyBindings,然后使用 #3 映射新值,然后使用 #4 映射新值(这些都不是 null),它可以完美运行。

【问题讨论】:

  • 一般提示:您不希望让 jQuery 在淘汰应用程序中进行任何顶级事件处理。唯一适合 jQuery 以任何方式接触 DOM 的地方(即附加到事件、修改 CSS 类、创建 HTML)是在自定义绑定处理程序中。所有主要的事件处理和 DOM 操作都应该通过敲除绑定来完成。
  • @Tomalak 感谢您的建议,这只是一个快速的模型,以便人们可以参考。真正的应用程序只在 ajax 调用之后映射数据,虽然我认为这仍然是一个 jQuery 事件。
  • 这就是为什么我说“以任何方式触及 DOM”。使用 jQuery 作为您的 Ajax 库很好。关键是您不希望 jQuery 在没有 Knockout 控制的情况下修改 DOM。 (只是为了它,这里有一个没有映射插件的变体:jsfiddle.net/hrgx5f1y/2

标签: javascript json knockout.js knockout-mapping-plugin


【解决方案1】:

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);
});

...它没有更新那个 observable,而是更新了 moreinfo 属性,所以它是空的。由于绑定是针对可观察对象而不是表达式,因此即使您更新视图模型以使moreinfo 不再为空,绑定表达式也不会重新计算;你的 DOM 仍然绑定到相同的原始 observable。

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

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

【讨论】:

    猜你喜欢
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    相关资源
    最近更新 更多