16

我有以下模型:

var model = {
   A: 'One',
   B: 'Two',
   C: 'Three'
};

我将各种 UI 元素绑定到这些字段,效果很好。但是,我将模型转换回 JavaScript 对象,以便可以将任何更改保存到服务器:

var goingToServer = ko.toJS(model);

goingToServer将包括属性 A、B 和 C。但是,假设属性 C 是一个永远不会改变的巨大数据块。我想避免将其发送回服务器。

有没有办法在将模型转换回 JavaScript 对象时toJS() 包含一组预定义的字段?

我一直在调查的一件事是Knockout Mapping 插件。它有一个名为include的设置,记录如下:

将您的视图模型转换回 JS 对象时,默认情况下,映射插件将仅包含原始视图模型的一部分的属性,但它还将包含 Knockout 生成的 _destroy 属性,即使它不是原始对象的一部分. 但是,您可以选择自定义此数组:

但是,这个插件似乎不像文档中那样工作,因为它ko.mapping.toJS()仍然包括 A、B 和 C,即使我传入include一个['A', 'B']. 我猜这个功能旨在包括原始模型中没有的其他字段。

有没有办法在将模型转换回 JavaScript 对象时排除某些属性,而不是做一些 hacky,例如生成对象并在发送到服务器之前手动删除我不想要的属性?

4

3 回答 3

28

你试过ignore关键字吗?它与 include 有类似的用法:

var mapping = {
    'ignore': ["propertyToIgnore", "alsoIgnoreThis"]
}
var viewModel = ko.mapping.toJS(data, mapping);

当您对服务器数据进行原始映射时,您可以只使用忽略,然后当您将其转换回 JS 时,它根本不会出现在您的对象上。

于 2013-02-20T19:30:31.383 回答
3

如果我们在 vm.Payment 下有一个复杂的对象模型实例,可观察引用为:

{
    "Summary": { 
        "Count": 12,
        "PaymentAmount": 1500,
        "PaymentMethod": "Cheque",
        "PaymentDate": "2015-04-08T22:38:48.552Z",
        "AgentOid": 1208795,
        "AgentName": "Asere Ware"
    }
    //[...]
}

并且只需要忽略一些内部属性,那么:

var mapping = {
    'ignore': ['Summary.PaymentMethod', 'Summary.PaymentDate'] //avoid lost some initialized values.
};
// map updating existing observable (Payment) under my ViewMode (vm) with source "data" JSON object.
ko.mapping.fromJS(data, mapping, vm.Payment);

这是 vm.Payment 内容的结果,其中仅保留了 PaymentMethod 和 PaymentDate:

{
    "Summary": { 
        "Count": 0,
        "PaymentAmount": 0,
        "PaymentMethod": "Cheque",
        "PaymentDate": "2015-04-08T22:38:48.552Z",
        "AgentOid": undefined,
        "AgentName": undefined
    }
    //[...]
}

于 2015-04-08T23:02:08.703 回答
2

好的,尽管我希望有更好的方法,但我已经找到了一种可行的解决方案。诀窍是在映射插件中忽略这些字段,然后将它们手动添加为计算字段。调用时,计算字段永远不会出现在生成的 JavaScript 对象toJS中。

// Utility function to quickly generate a computed field
ko.readonly = function (value)
{
   return ko.computed(function ()
   {
      return value;
   });
};

// View Model
var ViewModel = function (project)
{
   var readonly = ['B', 'C', 'D']; // Fields I want to ignore
   var mapping = {
      'ignore': readonly //Read-only properties, we'll add these manually as computed fields
   };

   // Use Mapping plugin to make everything observable, except the fields above
   ko.mapping.fromJS(project, mapping, this);

   // Now loop through the read only array and add these fields in as computed
   for(var i = 0; i < readonly.length; i++)
   {
      var field = readonly[i];
      this[field] = ko.readonly(project[field]);
   }
}

我现在可以正常绑定到这些视图模型:

ko.applyBindings(new ViewModel(data));
于 2013-02-20T21:04:59.927 回答