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
Exclude model properties when syncing (Backbone.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 selected
attributes on my model. Later, when I call .save()
on my collection, I'd want to ignore the value of selected
and 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 toJSON
function to whitelist attributes with _.pick
or blacklist attributes with _.omit
.
在 Underscore 1.3.3 中,他们添加了pick,在 1.4.0 中,他们添加了omit,可以非常简单地使用它来覆盖模型的toJSON
功能,以使用_.pick
将属性列入白名单或将属性列入黑名单_.omit
。
And since toJSON
is 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 contentType
if options.data
is already set:
根据几个答案,这说明了空对象的情况和 Backbone 中不发送contentType
if 的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 save
uses toJSON
we 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 selected
in views for example. Otherwise you probably need to override save
method.
但是,如果您使用 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 data
are sent to the server.
使用带有此属性的 save,只有按 as 传递的字段data
才会发送到服务器。