javascript 同步时排除模型属性 (Backbone.js)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13051966/
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 17:43:32  来源:igfitidea点击:

Exclude model properties when syncing (Backbone.js)

javascriptbackbone.jsunderscore.js

提问by Simon Boudrias

Is there a way to exclude certain property from my model when I sync?

当我同步时,有没有办法从我的模型中排除某些属性?

For example, I keep in my model information about some view state. Let's say I have a picker module and this module just toggle a selectedattributes on my model. Later, when I call .save()on my collection, I'd want to ignore the value of selectedand exclude it from the sync to the server.

例如,我将有关某些视图状态的信息保留在我的模型中。假设我有一个选择器模块,这个模块只是selected在我的模型上切换一个属性。后来,当我调用.save()我的收藏时,我想忽略 的值selected并将其从同步到服务器中排除。

Is there a clean way of doing so?

有没有一种干净的方法呢?

(Let me know if you'd like more details)

如果您想了解更多详细信息,请告诉我

回答by Simon Boudrias

This seems like the best solution (based on @nikoshr referenced question)

这似乎是最好的解决方案(基于@nikoshr 引用的问题)

Backbone.Model.extend({

    // Overwrite save function
    save: function(attrs, options) {
        options || (options = {});
        attrs || (attrs = _.clone(this.attributes));

        // Filter the data to send to the server
        delete attrs.selected;
        delete attrs.dontSync;

        options.data = JSON.stringify(attrs);

        // Proxy the call to the original save function
        return Backbone.Model.prototype.save.call(this, attrs, options);
    }
});

So we overwrite save function on the model instance, but we just filter out the data we don't need, and then we proxy that to the parent prototype function.

所以我们在模型实例上覆盖了保存函数,但我们只是过滤掉了我们不需要的数据,然后我们将它代理给父原型函数。

回答by byoungb

In Underscore 1.3.3 they added pickand in 1.4.0 they added omitwhich can be used very simply to override your model's toJSONfunction to whitelist attributes with _.pickor blacklist attributes with _.omit.

在 Underscore 1.3.3 中,他们添加了pick,在 1.4.0 中,他们添加了omit,可以非常简单地使用它来覆盖模型的toJSON功能,以使用_.pick将属性列入白名单或将属性列入黑名单_.omit

And since toJSONis used by the sync command for passing the data to the server I think this is a good solution as long as you do not want these fields wherever else you use toJSON.

并且由于toJSON同步命令使用它来将数据传递到服务器,我认为这是一个很好的解决方案,只要您不希望在其他任何地方使用这些字段toJSON

Backbone.Model.extend({
    blacklist: ['selected',],
    toJSON: function(options) {
        return _.omit(this.attributes, this.blacklist);
    },
});

回答by oak

my solution combine all the above. just use white list instead of black one .. this is good rule in general

我的解决方案结合了以上所有内容。只需使用白名单而不是黑名单..这是一般的好规则

define

定义

          attrWhiteList:['id','biography','status'],

and then overwrite the save

然后覆盖保存

  save: function(attrs, options) {
    options || (options = {});

 //here is whitelist or all
    if (this.attrWhiteList != null )
          // Filter the data to send to the server
             whitelisted =  _.pick(this.attributes, this.attrWhiteList);
    else  
        whitelisted =this.attributes;
    /* it seems that if you override save you lose some headers and the ajax call changes*/
    // get data
    options.data = JSON.stringify(whitelisted);

    if ((this.get('id') == 0) || (this.get('id') == null)) 
        options.type = "POST"
    else
        options.type = "PUT";


    options.contentType = "application/json";
     //        options.headers =  { 
     //            'Accept': 'application/json',
     //            'Content-Type': 'application/json' 
     //        },

    // Proxy the call to the original save function
   return  Backbone.Model.prototype.save.call(this, attrs, options);
},

回答by Pascal

In fact there is a much simpler way of achieving this without messing with backbone save or sync function since you would no be expecting this behaviour to be permanent

事实上,有一种更简单的方法可以实现这一点,而不会弄乱主干保存或同步功能,因为您不会期望这种行为是永久性的

if you look at backbone.js line 1145 you will see that

如果您查看backbone.js 第1145 行,您会看到

// Ensure that we have the appropriate request data.
    if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
      params.contentType = 'application/json';
      params.data = JSON.stringify(options.attrs || model.toJSON(options));
    }

Which means that you may override the data part of the xhr by putting data in your options

这意味着您可以通过将数据放在您的选项中来覆盖 xhr 的数据部分

Since backbone save requires model.save([attributes], [options])

由于主干保存需要 model.save([attributes], [options])

But remember that attributes like id might be essential to proper saving

但请记住,像 id 这样的属性对于正确保存可能是必不可少的

Example

例子

model.save( {}, { data: JSON.stringify(data) } ) ; 

So you should be doing something like this

所以你应该做这样的事情

var data = { id : model.id , otherAttributes : 'value' }  ;  
model.save( {}, { data : JSON.stringify(data) } );

This do the trick quite well for me and could be used with any backbone with xhr such as fetch, save, delete, ...

这对我来说非常有用,并且可以与任何具有 xhr 的主干一起使用,例如获取、保存、删除......

回答by Nacho

I found some problems with the accepted solution, as options.data modifies the way Backbone makes the calls. Better using options.attrs as this:

我发现已接受的解决方案存在一些问题,因为 options.data 修改了 Backbone 进行调用的方式。更好地使用 options.attrs 如下:

Backbone.Model.extend({
    save: function (attrs, options) {
        options = options || {};
        attrs = _.extend({}, _.clone(this.attributes), attrs);

        // Filter the data to send to the server
        delete attrs.selected;
        options.attrs = attrs;
        // Proxy the call to the original save function
        return Backbone.Model.prototype.save.call(this, attrs, options);
    }
});

回答by Ross Allen

Based on several of the answers, this accounts for cases of null objects and a conditional in Backbone that doesn't sent the contentTypeif options.datais already set:

根据几个答案,这说明了空对象的情况和 Backbone 中不发送contentTypeif 的options.data条件已经设置:

EDITABLE_ATTRIBUTES = ["name", "birthdate", "favoriteFood"];

...

save: function(attrs, options) {
  // `options` is an optional argument but is always needed here
  options || (options = {});

  var allAttrs = _.extend({}, this.attributes, attrs);
  var allowedAttrs = _.pick(allAttrs, EDITABLE_ATTRIBUTES);

  // If `options.data` is set, Backbone does not attempt to infer the content
  // type and leaves it null. Set it explicitly as `application/json`.
  options.contentType = "application/json";
  options.data = JSON.stringify(allowedAttrs);

  return Backbone.Model.prototype.save.call(
    this, allowedAttrs, options);
},

回答by John Xiao

Set options.attrs will allow you customise api param:

设置 options.attrs 将允许您自定义 api 参数:

var model = new Backbone.Model();
model.save(null, {
  wait: true,
  success: function() {
  },
  attrs: _.omit(model.attributes, 'selected')
});

回答by rinat.io

Since saveuses toJSONwe override it:

由于save使用toJSON我们覆盖它:

    toJSON: function(options) {
        var attr = _.clone(this.attributes);
        delete attr.selected;
        return attr;
    },

But it may not work if you're using toJSON and need selectedin views for example. Otherwise you probably need to override savemethod.

但是,如果您使用 toJSON 并且需要selected在视图中使用,则它可能不起作用。否则,您可能需要覆盖save方法。

回答by Tallmaris

If it is a one-off occasion, you could use mode.unset('selected', { silent:true })(silent is set only to avoid firing the change event), to remove the attribute... This has the not so nice counter-effect of having to re-set it after saving though.

如果它是一次性的,你可以使用mode.unset('selected', { silent:true })(静音设置只是为了避免触发更改事件),删除属性......这具有在保存后必须重新设置的不太好的反作用尽管。

This said, I totally endorse one of the solutions above. Moreover if this is something you need on a more regular basis.

这就是说,我完全赞同上述解决方案之一。此外,如果这是您经常需要的东西。

回答by Pavel Sedek

To set only desired values, use HTTP PATCH insead of HTTP POST. On the backbone side, just add a patch attribute to the save method:

要仅设置所需的值,请使用 HTTP PATCH 代替 HTTP POST。在主干端,只需在 save 方法中添加一个补丁属性:

entity.save(data,{patch:true})

Using save with this attribute, only fields passed as dataare sent to the server.

使用带有此属性的 save,只有按 as 传递的字段data才会发送到服务器。