5

私はかなり一般的なモデルとそのモデルのコレクション (以下を参照) を持っており、一連のビューの基礎として扱っています。いくつかのビューでは、モデルの 1 つを選択すると ('selected' 属性を介して) アクションが生成され、クライアント側だけで選択を追跡できるようにする必要があります。

ただし、バックボーンでこれを行うクリーンな方法はないようです。クライアント上のモデルに追加/変更された属性は、サーバーに同期されます。イベントがその属性で発生した{silent : yes}ときにビューで変更をトリガーする必要があるため、その属性を変更するときに使用できません。changeこれを行うために私が思いついた唯一の方法は、save関数を上書きすることですBackbone.Model

私の質問: 私が見逃しているクライアント側のみの属性を持つ方法はありますか、それとも私のアプローチは、私が見ていない他の方法で構造的に欠陥がありますか?

    var CSEvent = Backbone.Model.extend({
        idAttribute: "_id",
        urlRoot : '/api/events',
        defaults: {
            title : "",
            type : "Native",
            repeatOrOneTime : "OneTime",
            selected : false
        }
    });    

    var CSEventCollection = Backbone.Collection.extend({
        model: CSEvent,
        url: '/api/events',
        getSelectedEvent : function() {
            return this.find(function(csevent) { return csevent.get('selected') === true; });
        },
        selectEvent : function(eventId) {
            this.deselectEvent();
            this.get(eventId).set({selected : true});
        },
        deselectEvent : function() {
            this.getSelectedEvent().set({selected : false});
        }
    });
4

3 に答える 3

5

バックボーン モデル コードModel.toJSON()でわかるように、このメソッドはそれほど複雑ではありません。また、公式ドキュメントでは、特別な必要がある場合に備えてオーバーライドすることを提案しています。

次のようなことを試してください:

var CSEvent = Backbone.Model.extend({
  toJSON: function(){
    return _.clone( _.pick( this.attributes, "title", "type", "repeatOrOneTime" ) );
  }
});
于 2012-08-13T19:53:01.890 に答える
1

Model.toJSON()バックボーン モデルをマイクロ テンプレートに渡す場合など、おそらくコードの他の部分で JSON 表現を使用する必要があるため、オーバーライドすることはお勧めしません。

保存される属性をカスタマイズするより良い方法は、Model オブジェクトでsync メソッドをオーバーライドすることです。

   sync: function(method, model, options) {
        if (method == 'update' || method == 'create') {
            var newModel = this.clone();
            newModel.unset('ignoredAttribute', {silent: true);
            return Backbone.sync.call(newModel, method, newModel, options);
        } else {
            return Backbone.sync.call(this, method, this, options);
        }
    },

この例では、 という属性を無視していますignoredAttribute

コードでは、次のようになります。

  var CSEvent = Backbone.Model.extend({
    idAttribute: "_id",
    urlRoot : '/api/events',
    defaults: {
        title : "",
        type : "Native",
        repeatOrOneTime : "OneTime",
        selected : false
    },
    sync: function(method, model, options) {
        if (method == 'update' || method == 'create') {
            var newModel = this.clone();
            newModel.unset('selected', {silent: true);
            return Backbone.sync.call(newModel, method, newModel, options);
        } else {
            return Backbone.sync.call(this, method, this, options);
        }
    }
});   

もう 1 つの簡単なオプションは、selected(バックボーン管理属性としてではなく) オブジェクト属性として配置することですtrigger。私にとって、これはあなたの問題に対する最も簡単な解決策です:

  var CSEvent = Backbone.Model.extend({
    idAttribute: "_id",
    urlRoot : '/api/events',
    selected : false,
    defaults: {
        title : "",
        type : "Native",
        repeatOrOneTime : "OneTime"
    },
    select: function() {
         this.selected = true;
         this.trigger('selected'); // you can use another event name here, ie. change
    },
    deselect: function() {
         this.selected = false;
         this.trigger('deselected');
    }
});   
于 2012-08-14T03:51:43.947 に答える
1

をオーバーライドせずに、上記の 2 つの原則を使用してこれを達成する方法を提案したいと思いますtoJSON()

このパターンには多くの利点があります。たとえば、必要な属性のみをサーバーに送信する前に、クライアント側ですべての属性を検証できます。

次の例では、ユーザーがパスワードを変更する方法を提供しています。

var UserModel = Backbone.Model.extend({

  defaults: {
    username: "",
    password: {
      old: "",
      new: "",
      confirm: ""
    }
  },

  validate: function(attrs) {
    if (attrs.password.new !== attrs.password.confirm) {
      return "Passwords must match";
    }
  },

  toRemoteJSON: function() {
    var payload = this.toJSON();
    delete payload.password.confirm;
    return payload;
  },

  sync: function(method, model, options) {
    if (method == 'update' || method == 'create') {
      var newModel = this.clone();
      newModel.clear({ silent: true });
      newModel.set(this.toRemoteJSON(), { silent: true });
      return Backbone.sync.call(newModel, method, newModel, options);
    } else {
      return Backbone.sync.call(this, method, this, options);
    }
  }

});

モデルがsaved の場合、validate()メソッドはメソッドの前に呼び出されるsync()ため、2 つの新しいパスワードが一致するかどうかがチェックされます。次に、このメソッドは、サーバーに送信する前にパスワードの確認フィールドを削除するようsyncデリゲートします。toRemoteJSON()

このtoRemoteJSON()関数はnewModel.unset()、Diego のソリューションの一部を単純に抽象化したものです。syncしかし、これは、オーバーライドされたオブジェクトをベース オブジェクトで定義できることを意味し、これから拡張するオブジェクトは を定義するだけで済みますtoRemoteJSON()

于 2012-10-05T10:53:33.677 に答える