backbone.js:自上次服务器保存以来是否有变化?

时间:2012-02-09 16:46:10

标签: javascript backbone.js

我有一个骨干模型。 使用model.set()我可以设置一个本地值,使用model.save()我可以将整个模型保存到服务器。

我如何知道自上次服务器保存以来是否有更改,这意味着本地版本是脏的。

model.isNew();仅在模型从未保存到服务器时才起作用。

5 个答案:

答案 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()以来哪些属性发生了变化,并且它适用于模型和集合。

https://github.com/ChiefORZ/backbone.dirty-sync