如何使用敲除映射将空值映射到空的可观察数组

How do you use knockout mapping to map from a null value to an empty observable array?

本文关键字:映射 数组 观察 空值 何使用      更新时间:2023-09-26

当我试图使用敲除映射从空json属性映射到敲除可观察数组时,我遇到了一个问题。在执行映射之后,剔除数组为空。

例如,我有以下数据:

var data = { 'Name': 'David', 'Modules': null };

以及以下型号:

var ModuleViewModel = function(data) {
    var self = this;
    ko.mapping.fromJS(data, {}, self);
};
var Model = function(data) {
    var self = this;
    var mapping = {
      'Modules': {
        key: function(module) {
            return ko.utils.unwrapObservable(module.Id);
        },
        create: function (options) {
            return new ModuleViewModel(options.data);
        }
      }
    };
    ko.mapping.fromJS(data, mapping, self);
};

然后使用将其应用于视图

var model = new Model(data);
ko.applyBindings(model);

在这种观点中,简单地说:

<span data-bind="text: Name"></span>
<span data-bind="text: Modules().length"></span>

我想看到的(在我的名字后面)是已经映射的模块的数量。如果数据中存在模块:

var data = { 'Name': 'David', 'Modules': [ {'Id': '1', 'Name': 'Module1'} ] }

然后在视图上显示正确的数字,但如果模块在数据中设置为null,则该数字根本不显示,因为它不知道映射到可观察阵列。

此外,如果我在视图模型上定义了一个额外的属性来映射到:

self.Modules = ko.observableArray;

这仍然没有像我所期望的那样被映射,就像你在映射后查询self.Modules(),你得到了一个返回的null值,而如果你查询一个正常的空可观察数组,你得到的是[]

我在映射中做错了什么?我只想在模块数据为null时显示一个0值。

单击此处使用jsbin 进行编辑

这里有一个您可能会觉得有用的映射更新。

http://jsbin.com/zeguxiveyi/1

重要的是要注意以下变化。

首先,您没有应用映射。

// need to invoke the mapping object
ko.mapping.fromJS(data, mapping, self);

其次,用null调用observable没有多大意义。。。这就像吃甜甜圈的洞,对吧?

//Initialize your data with null modules :: ERROR
//For the sake of having an empty observable array, we need to convert this null to an empty array
var data = { 'Name': 'David', 'Modules': null };
if(data.Modules == null) data.Modules = [];

第三,在你可能得到零的情况下,你应该继续添加一点短路逻辑来防止它…

var mapping = {
 'Modules': {
    create: function (options) {
      if(options.data !== null)
        return new ModuleViewModel(options.data);
    }
  }
};

总而言之,映射插件很有用,但它并没有什么神奇之处……仍然需要确保你的数据是合理的。

您可以放置一个计算的可观察对象进行null检查,并尽可能保持其干净,如下所示:

var ModuleViewModel = function(data) {
    var self = this;
    ko.mapping.fromJS(data, {}, self);
    //After mapping the object, add the computed observable here
    self.numberOfModules = ko.computed(function() {
        return this.Modules ? this.Modules().length : 0;
    }, self);
};

然后在您的绑定中:

<span data-bind="text: numberOfModules">

如果computed用于HTML中的许多不同位置,以避免到处重复null检查,那么这将非常方便。