我有一个骨干模型。 使用model.set()我可以设置一个本地值,使用model.save()我可以将整个模型保存到服务器。
我如何知道自上次服务器保存以来是否有更改,这意味着本地版本是脏的。
model.isNew();仅在模型从未保存到服务器时才起作用。
答案 0 :(得分:16)
编辑:此答案是在1.0版Backbone之前编写的。截至目前的Backbone版本(1.2.2)hasChanged
不再反映"自上次保存"变化。相反,它反映了自上次设置"。
收听更改事件或检查hasChanged
。
如果模型已更改,您可以保存更改。您甚至可以在更改事件发生时将保存方法连接到触发器。
如果您不想保存更改,请为模型设置一个脏的属性,并在明确保存时将其清除。
类似的东西:
change: function(){
this.dirty = true;
}
save: function(){
// do your save
if(success){
this.dirty = false;
}
}
isDirty: function(){
return this.dirty
}
答案 1 :(得分:5)
我正在使用CouchDB,而Couch的_rev属性在每次保存成功后都会发生变化。我通过在模型初始化函数中放置以下代码解决了“自上次服务器保存”的问题:
initialize : function() {
this.on('change',function(){
if(this.hasChanged('_rev')) {
this.isSaved = true;
}else{
this.isSaved = false;
}
},this);
}
答案 2 :(得分:4)
备用选项是将所有更新设置为“静默”更新,然后在您要同步时收集更改:
// Updates
myModel.set({foo: 'bar'}, {silent: true}); // Does not fire a 'changed' event
myModel.set({foobar: 'barfoo'}, {silent: true});
// Sync
if (myModel.hasChanged()) {
console.log(myModel.changedAttributes()); // {'foo':'bar', 'foobar':'barfoo'}
_.each(myModel.changedAttributes(), function(value, key) {
console.log(key+' used to be '+myModel.previous(key)+', but now is '+value);
}
myModel.save();
}
答案 3 :(得分:0)
除非您通过{silent:true}选项,否则所有建议侦听更改(使用事件)的答案都是正确的。在这种情况下,您需要覆盖默认的set方法以保存已更改的属性,并在调用save方法后重置该列表。
MidnightLightning的回答不正确。如果你调用set方法两次,那么changedAttributes将只返回自上次调用以来有变化的属性 - 它在Backbone文档中:
changedAttributesmodel.changedAttributes([attributes])
仅检索自上次设置以来已更改的模型属性的哈希值,如果没有则返回false。
就我而言,我用这段代码解决了问题:
(function(_, Backbone) {
'use strict';
var _set = Backbone.Model.prototype.set,
_save = Backbone.Model.prototype.save;
_.extend(Backbone.Model.prototype, {
set: function(key, val, options) {
var options = this._getOptions(key, val, options),
toReturn = _set.call(this, key, val, options);
if(!_.isUndefined(options) && options.silent && !!this.changedAttributes()) {
this.silentChanges = _.extend([], this.silentChanges);
[].push.apply(this.silentChanges, _.keys(this.changedAttributes()));
}
return toReturn;
},
save: function(key, val, options) {
var options = this._getOptions(key, val, options),
toReturn = _save.call(this, key, val, options);
if(!_.isUndefined(options) && options.triggerSilents) {
this.triggerSilentChanges();
}
return toReturn;
},
unset: function(key, options) {
if(!_.isUndefined(options) && options.silent) {
this.silentChanges = _.extend([], this.silentChanges, _.keys(this.changedAttributes()));
}
},
triggerSilentChanges: function() {
if(!_.isEmpty(this.silentChanges)) {
var that = this;
_.each(this.silentChanges, function(key) {
that.trigger('change:' + key);
that.silentChanges = _.without(that.silentChanges, key);
});
Backbone.Model.prototype.trigger.call(this, 'change');
}
},
_getOptions: function(key, val, options) {
if(key == null || _.isObject(key)) {
return val;
}
return options;
}
});
})(_, Backbone);
如果我想获得所有更改的属性,我在模型中使用silentChages属性。 如果我想在保存时触发所有set / unset属性的事件,我添加'triggerSilents:true'选项。我也可以通过调用triggerSilentChanges方法手动触发所有更改事件。
答案 4 :(得分:0)
仅供参考,我制作了一个代码片段,取代了默认的Backbone.sync方法。
替换后的Backbone.sync确定了自上次save()以来哪些属性发生了变化,并且它适用于模型和集合。