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

Sim*_*ias 43 javascript backbone.js underscore.js

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

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

这样做有干净的方法吗?

(如果您想了解更多细节,请告诉我)

Sim*_*ias 47

这似乎是最好的解决方案(基于@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);
    }
});
Run Code Online (Sandbox Code Playgroud)

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

  • attrs可能为null所以做JSON.stringify(attrs || this.attributes)而不是..或JSON.stringify(_.pick(attrs || this.attributes,"f1","f2",...))for白名单 (3认同)

byo*_*ngb 35

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

由于toJSONsync命令用于将数据传递到服务器,因此我认为这是一个很好的解决方案,只要您不想在任何其他地方使用这些字段toJSON.

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

  • `_pick`和`_.omit`很棒,我使用它们,但是在`save`中,而不是`toJSON`.`toJSON`方法的问题在于它过滤掉了视图所需的数据,而不仅仅是保存到服务器. (17认同)

oak*_*oak 11

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

限定

          attrWhiteList:['id','biography','status'],
Run Code Online (Sandbox Code Playgroud)

然后覆盖保存

  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);
},
Run Code Online (Sandbox Code Playgroud)


Pas*_*cal 6

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

如果你看看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));
    }
Run Code Online (Sandbox Code Playgroud)

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

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

但请记住,像id这样的属性可能对正确保存至关重要

model.save( {}, { data: JSON.stringify(data) } ) ; 
Run Code Online (Sandbox Code Playgroud)

所以你应该做这样的事情

var data = { id : model.id , otherAttributes : 'value' }  ;  
model.save( {}, { data : JSON.stringify(data) } );
Run Code Online (Sandbox Code Playgroud)

这对我来说非常好,可以与xhr的任何骨干一起使用,例如fetch,save,delete,...

  • 这适用于个案需求.不要过滤每次显示相关属性.但它是一个有效的解决方案,并且比这里针对"逐案"解决方案提出的方法更容易. (2认同)