javascript 如何从 Knockoutjs toJS() 中排除某些属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14988220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 23:04:42  来源:igfitidea点击:

How to exclude certain properties from Knockoutjs toJS()

javascriptknockout.jsknockout-mapping-plugin

提问by Mike Christensen

I have the following model:

我有以下模型:

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

I bind various UI elements to these fields, which works great. However, I convert the model back to a JavaScript object so I can save any changes to the server:

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

var goingToServer = ko.toJS(model);

goingToServerwill include properties A, B and C. However, let's say property C is a huge chunk of data that will never change. I'd like to avoid sending this back to the server.

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

Is there a way to make toJS()onlyinclude a predefined set of fields when converting a model back to a JavaScript object?

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

One thing I've been investigating is the Knockout Mapping plugin. It has a setting called includewhich is documented as such:

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

When converting your view model back to a JS object, by default the mapping plugin will only include properties that were part of your original view model, except it will also include the Knockout-generated _destroy property even if it was not part of your original object. However, you can choose to customize this array:

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

However, it appears this plugin doesn't work as documented, as ko.mapping.toJS()will still include A, B and C, even if I pass in an includearray of ['A', 'B']. I'm guessing this feature is intended to include additionalfields that were not in the original model.

然而,看来这插件不工作作为记录,因为ko.mapping.toJS()仍然将包括A,B和C,即使我通过在一个include阵列['A', 'B']。我猜这个功能旨在包含原始模型中没有的其他字段。

Is there a way to exclude certain properties when converting a model back to a JavaScript object, short of doing something hacky such as generating the object and manually removing the properties I don't want before sending to the server?

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

回答by Paul Manzotti

Have you tried the ignorekeyword? It has a similar usage to the include:

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

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

You could just use ignore when you do the original mapping of the server data, then it won't be on your object at all when you convert it back to JS.

您可以在对服务器数据进行原始映射时使用 ignore ,那么当您将其转换回 JS 时,它根本不会在您的对象上。

回答by Asereware

If we have a complex object model instance under vm.Payment observable reference as:

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

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

and need to ignore only some inner properties, then:

并且只需要忽略一些内部属性,然后:

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

and this is the result for vm.Payment content, where only PaymentMethod and PaymentDate are keept:

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

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

回答by Mike Christensen

Ok, I've figured out one solution that works though I'm hoping there's a better approach. The trick is to ignorethese fields in the mapping plugin, then add them in manually as computed fields. Computed fields will never end up in the generated JavaScript object when toJSis called.

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

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

I can now bind to these view model as normal:

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

ko.applyBindings(new ViewModel(data));