同步时有没有办法从我的模型中排除某些属性?
例如,我在模型中保留有关某些视图状态的信息。假设我有一个选择器模块,这个模块只是selected
在我的模型上切换一个属性。稍后,当我调用.save()
我的集合时,我想忽略 的值selected
并将其从同步到服务器中排除。
有没有一种干净的方法呢?
(如果您想了解更多详情,请告诉我)
同步时有没有办法从我的模型中排除某些属性?
例如,我在模型中保留有关某些视图状态的信息。假设我有一个选择器模块,这个模块只是selected
在我的模型上切换一个属性。稍后,当我调用.save()
我的集合时,我想忽略 的值selected
并将其从同步到服务器中排除。
有没有一种干净的方法呢?
(如果您想了解更多详情,请告诉我)
这似乎是最好的解决方案(基于@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,在 1.4.0 中,他们添加了omit,它可以非常简单地用于覆盖模型的toJSON
功能,以将属性列入白名单_.pick
或将属性列入黑名单_.omit
。
由于toJSON
同步命令用于将数据传递到服务器,因此我认为这是一个很好的解决方案,只要您不希望在其他任何地方使用这些字段toJSON
。
Backbone.Model.extend({
blacklist: ['selected',],
toJSON: function(options) {
return _.omit(this.attributes, this.blacklist);
},
});
我的解决方案结合了以上所有内容。只需使用白名单而不是黑名单.. 一般而言,这是一个很好的规则
定义
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);
},
事实上,有一种更简单的方法可以实现这一点,而不会弄乱主干保存或同步功能,因为您不会期望这种行为是永久性的
如果您查看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 的主干一起使用,例如获取、保存、删除......
基于几个答案,这说明了空对象的情况和 Backbone 中未发送contentType
ifoptions.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);
},
我发现接受的解决方案存在一些问题,因为 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);
}
});
由于save
使用toJSON
我们覆盖它:
toJSON: function(options) {
var attr = _.clone(this.attributes);
delete attr.selected;
return attr;
},
selected
但是如果你使用 toJSON 并且需要在视图中,它可能不起作用。否则你可能需要重写save
方法。
设置 options.attrs 将允许您自定义 api 参数:
var model = new Backbone.Model();
model.save(null, {
wait: true,
success: function() {
},
attrs: _.omit(model.attributes, 'selected')
});
如果这是一次性的场合,您可以使用mode.unset('selected', { silent:true })
(设置静音只是为了避免触发更改事件)来删除属性......这有一个不太好的反效果,必须在保存后重新设置它尽管。
这就是说,我完全赞同上述解决方案之一。此外,如果这是您更经常需要的东西。
要仅设置所需的值,请使用 HTTP PATCH 而不是 HTTP POST。在主干端,只需在 save 方法中添加一个补丁属性:
entity.save(data,{patch:true})
使用带有此属性的保存,只有作为传递的字段data
被发送到服务器。
遇到同样的问题,我决定创建一个可以提供帮助的小模块:https ://github.com/lupugabriel1/backbone-model-save
这是您可以在模型中使用它的方式:
var myModel = new Backbone.ModelSave.extend({
notSync: ['name', 'age']
});