同步时排除模型属性(Backbone.js)
当我同步时,是否有办法从我的模型中排除某些属性?
例如,我在我的模型信息中保留了一些视图状态。 比方说,我有一个select器模块,这个模块只是在我的模型上切换selected
属性。 后来,当我在我的集合上调用.save()
时,我想忽略selected
的值,并将其从同步到服务器中排除。
有没有一个干净的方式呢?
( 让我知道你是否想要更多的细节 )
这似乎是最好的解决scheme(基于@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); } });
所以我们在模型实例上覆盖了保存函数,但是我们只是过滤掉了我们不需要的数据,然后我们将其代理到父级原型函数中。
在Underscore 1.3.3中,他们添加了pick和in 1.4.0,他们添加了omit ,它可以很简单地用你的模型的toJSON
函数把_.pick
或者blacklist属性白名单join_.omit
。
而且由于toJSON
被sync命令用于将数据传递给服务器,所以我认为这是一个很好的解决scheme,只要你不需要这些字段,无论你使用toJSON
使用toJSON
。
Backbone.Model.extend({ blacklist: ['selected',], toJSON: function(options) { return _.omit(this.attributes, this.blacklist); }, });
我的解决scheme结合了以上所有。 只是使用白名单而不是黑名单..这是一般的好规则
确定
attrWhiteList:['id','biography','status'],
然后覆盖保存
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); },
事实上,有一个更简单的方法来实现这一点,而不会干扰主干保存或同步function,因为你不会期望这种行为是永久的
如果你看看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)); }
这意味着你可以通过将数据放在你的选项中来覆盖xhr的数据部分
由于骨干保存需要model.save([attributes],[options])
但请记住,像ID这样的属性可能是正确保存的关键
例
model.save( {}, { data: JSON.stringify(data) } ) ;
所以你应该做这样的事情
var data = { id : model.id , otherAttributes : 'value' } ; model.save( {}, { data : JSON.stringify(data) } );
这个技巧对我来说很好,可以和任何支持xhr的骨干一起使用,例如抓取,保存,删除,…
基于几个答案,这将解决null对象的情况,以及Backbone中的条件,如果options.data
已经设置,则不发送contentType
:
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); },
自save
使用toJSON
我们覆盖它:
toJSON: function(options) { var attr = _.clone(this.attributes); delete attr.selected; return attr; },
但是,如果您使用toJSON并且需要在视图中selected
,则它可能不起作用。 否则,你可能需要重写save
方法。
设置options.attrs将允许你自定义API参数:
var model = new Backbone.Model(); model.save(null, { wait: true, success: function() { }, attrs: _.omit(model.attributes, 'selected') });
我发现接受的解决scheme有一些问题,因为options.data修改了骨干进行呼叫的方式。 更好地使用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); } });
如果是一次性的,你可以使用mode.unset('selected', { silent:true })
(沉默只是为了避免触发变化事件),删除属性…这有没有所以保存后不得不重新设置它的好反效果。
这就是说,我完全赞同上面的解决scheme之一。 此外,如果这是你需要更经常的事情。
要仅设置所需的值,请使用HTTP POST的HTTP PATCH insead。 在骨干端,只需要在save方法中添加一个补丁属性:
entity.save(data,{patch:true})
使用此属性保存,只有在data
发送到服务器时传递的字段。
有同样的问题,我决定创build一个小模块,可以帮助: https : //github.com/lupugabriel1/backbone-model-save
这就是你可以在你的模型中使用它的方法:
var myModel = new Backbone.ModelSave.extend({ notSync: ['name', 'age'] });