【问题标题】:ComputedObservables doesn't recalc after ko.mapping.fromJS在 ko.mapping.fromJS 之后,ComputedObservables 不会重新计算
【发布时间】:2016-05-18 19:07:11
【问题描述】:

我正在使用 KnockoutJS,并且我有一个嵌套的 ViewModel-Structure,每个级别都有 Computed Observables。父级包含其子级的总计。数据结构看起来像这样(简化):

vm.clientsRawData = [
    {
        ClientName: "Thomas",
        MoneyAccounts: [
            {
                Currency: "USD",
                Amount: "1000"
            }
            {
                Currency: "EUR",
                Amount: "2000"
            }
        ]
    },
    {
        ClientName: "Ann",
        MoneyAccounts: [
            {
                Currency: "CHF",
                Amount: "4000"
            }
            {
                Currency: "EUR",
                Amount: "1500"
            }
        ]
    }
]

初始化 ViewModel(使用 ko.mapping.fromJS)后,我看到“顶级(例如,vm.AllUsd(),包含每个客户 Usd MoneyAccounts 的总和)”上的 ComputedObservables 没有刷新. Sum 仍然是 0。我需要做什么才能在 JS-Structure 的映射中计算这个总量?

我已经尝试使用 dummy-observables 来实现这一点,但这会极大地减慢加载过程(浏览器不堪重负,挂断)

提前致谢

更新:例如,这个例子。我发现,初始化后 Client-Count 为 0。但为什么呢?

var ClientsMapping = {
  create: function (options) {
    var client = ko.mapping.fromJS(options.data, ContainersMapping)
    //Some computed observables for level one here...
    return client;
  }
}
var ContainersMapping = {
  'Containers': {
    create: function (options) {
      var container = ko.mapping.fromJS(options.data, MoneyAccountsMapping)
      container.totalChf = ko.computed(function () {
        var total = 0;
        $.each(container.MoneyAccounts(), function () {
          if (this.Currency() == "CHF") {
            total += this.Amount();
          }
        })
        return total;
      })
      //Some computed observables for level two here...
      return container;
    }
  }
}

var MoneyAccountsMapping = {
  'MoneyAccounts': {
    create: function (options) {
      var macc = new MoneyAccountModel(options.data)
      //Some computed observables for level three here...
      return macc;
    }
  }
}
var ClientModel = function (data) {
  ko.mapping.fromJS(data, {}, this);
}
var ContainerModel = function (data) {
  ko.mapping.fromJS(data, {}, this);
}
var MoneyAccountModel = function (data) {
  ko.mapping.fromJS(data, {}, this);
}
var data = [
  {
    'Clients': 'Thomas',
    'Containers': [
      {
        'ContName': 'Cont01',
        'MoneyAccounts': [
          { Currency: "CHF", Amount: 1000 },
        ]
      }
    ]
  },
{
  'Clients': 'Ann',
  'Containers': [
    {
      'ContName': 'Cont01',
      'MoneyAccounts': [
        { Currency: 'CHF', Amount: 1000 },
        { Currency: 'EUR', Amount: 500 }
      ]
    }
  ]
}
]

function viewModel() {
  var self = this;
  self.clients = ko.observableArray()
  self.clientsCount = ko.computed(function () {
    return self.clients().length
  })
}
var vm;
$(function () {
  vm = new viewModel();
  vm.clients = ko.mapping.fromJS(data, ClientsMapping);
})

【问题讨论】:

  • 你能添加你用来创建 ViewModel 的代码吗?需要注意的一点是 ko.mapping.fromJS() 每次调用都会创建一个新的引用。因此,如果您调用 vm.clientList = ko.mapping.fromJS(vm.clientsRawData) 并创建一些 observables,那么如果您再次调用 vm.clientList = ko.mapping.fromJS(vm.clientsRawData),它会创建一个新的引用,但是计算出的 observables 仍将指向旧的引用。
  • rollback the question to version 2 并将解决方案作为答案发布在下面:让其他人更容易发现。
  • @Jeroen 完成。感谢您的反馈。

标签: javascript jquery mvvm knockout.js


【解决方案1】:

好的,知道了。我不得不像这样调用客户 observableArray:

vm.clients(ko.mapping.fromJS(data, ClientsMapping)())

非常感谢 Eric 为我指明了正确的方向。你救了我! :-)

【讨论】:

    猜你喜欢
    • 2012-10-11
    • 2012-11-24
    • 2014-04-04
    • 1970-01-01
    • 2017-03-01
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    相关资源
    最近更新 更多