Backbone: Backbone.Modelに「リセット」メソッドを追加します

作成日 2014年07月31日  ·  22コメント  ·  ソース: jashkenas/backbone

サーバーから受信したモデルのデータの一部を更新する必要がありました。 現在、2つのオプションがあります。 Model.set呼び出すか、 Model.attributes直接設定します。 変更を記録したくありませんsilentたが、それぞれのビューを更新する必要があったため、

Backbone.Model.prototype.reset = (attributes, options) ->
    attrs = attributes || {};
    if options.parse
      attrs = this.parse(attrs, options) || {}

    @set(attrs, options);
    <strong i="9">@changed</strong> = {};

Backbone.Model Backbone.Collectionようなリセットメソッドがないのはなぜだろうか?

question

最も参考になるコメント

@ thesmart 、Model#setは欠落している属性の設定を解除しないため、Model#resetが必要だと思います。

問題をクローズするときに理由を説明する必要があります。 @ akre54がこれを閉じた理由を知りたいのですが。 バックボーンモデルは意図的に原始的であり、非ピニオン化されていますが、Model#resetがないことは、モデルの使用方法についての意見を表しています。 http://backbonejs.org/#Getting-startedから

哲学的には、Backboneは、JavaScriptを使用してWebアプリケーションを構築するときに一般的に役立つデータ構造化(モデルとコレクション)およびユーザーインターフェイス(ビューとURL)プリミティブの最小限のセットを発見する試みです。

全てのコメント22件

リセットはエスケープハッチであり、必要であることがわかっているときに、効率的なレンダリングを一括で簡単に実行できます。

あなたの場合は、 set使用してください。

属性を汚さずに設定できますか?

2014年8月1日には、7:28で、ジェレミー・アッシュケナスの[email protected]書きました:

リセットはエスケープハッチであり、必要であることがわかっているときに、効率的なレンダリングを一括で簡単に実行できます。

あなたの場合は、setを使用してください。


このメールに直接返信するか、GitHubで表示してください。

呼び出しModel.clear()の前にModel.set({})あなたのケースで動作しますか? この方法では、現在の属性を拡張せず、代わりに置き換えられます。 Model.clear()は、モデルで2つの「変更」イベントをトリガーしたくない場合のサイレントオプションもサポートします。

私はこの方法が欠けていることに同意します。 model.clear()model.set()を組み合わせて使用​​することも考えました。 次に、 changeイベントを2回トリガーするという問題に遭遇しました。
model.clear()呼び出すときにsilentオプションを使用することはオプションではありません。これは、プロパティが設定解除されたときにchangeイベントを発生させたいためです。

model.reset()メソッドは、新しい属性ハッシュを取得し、このハッシュに、新しい属性ハッシュに存在しない古い属性キーのundefined値を入力します。

Model.prototype.reset = function(attrs, options) {
    for (var key in this.attributes) {
        if (key in attrs) continue;
        attrs[key] = void 0;
    }

    return this.set(attrs, options);
};

@lennerd

どうですか:

Model.prototype.reset = function(attrs, options) {
    for (var key in this.attributes) {
        this.unset(key, {silent:true});
    }
    return this.set(attrs, options);
};

いいえ、これは役に立ちません。 モデルの現在の属性ハッシュにキーfooがあるとします。これは、 model.reset()渡す新しいattrsハッシュには存在しません。 change:fooイベントをリッスンすると、サイレントモードでmodel.unset()を使用したため、新しい値undefinedでトリガーされません。

Backbone.Model.prototype.reset = function(attrs, options) {
    for (var key in this.attributes) {
        this.unset(key, {silent:true});
    }
    return this.set(attrs, options);
};

var bar = new Backbone.Model();

bar.on('change', function(model) {
    console.log('The model bar has been changed.');
});

bar.on('change:foo', function(model, foo) {
    console.log('Foo has been changed to: ' + foo);
});

bar.set(foo, 'test');
// => The model bar has been changed.
// => Foo has been changed to: test

bar.reset({ foo2: 'test2' });
// => The model bar has been changed.
// Foo was resetted but no change event has been triggered.

http://jsfiddle.net/lennerd/3s1Ltwgu/

かっこいい、私はあなたが意味することを理解します。 this.attributesを明示的にオーバーライドするよりもthis.unset(key, options)を使用することを選択するでしょうが、それはattrs[key] = void 0;を交換するだけの問題です:panda_face:

私はまだbackbone.jsに比較的慣れていないので、私が示す無知を許してください。しかし、議論されている振る舞いはModel.fetchように聞こえます。 説明は言う:

サーバーからモデルの状態をリセットします

changeイベントは引き続きトリガーされているように見えますが、モデルを「ダーティ」にしないでください。 サーバーの応答に基づいて属性をリセットしようとしているときに、このアプローチを採用できない理由はありますか? このような状況が発生する可能性があるのは、別の操作の副作用としてモデルが変更された場合だけだと思いますが、一般に、このような副作用はプログラミングが不十分であると見なされ、可能であれば回避する必要があります。 副作用を回避できない場合は、新しいモデル属性の代わりに「モデルXYZの更新」応答フラグを送信し、そのような応答が表示されるたびにfetchをトリガーする方が理にかなっています。

繰り返しますが、私がこのコメントで示している無知を許してください。

@kolorahl

OPが達成したいのは、現在のモデル属性をクリアし、モデルの新しい属性となる新しいJSONを渡すことです。 このように、すでにJSONがある場合は、バックエンドにアクセスする必要はありません。

私はどういうわけか彼のclear + setメソッドで@ lupugabriel1に同意します。 しかし、これは考慮する必要がある機能の1つだと思います。 Backbone.Collection#resetのようなもの

私がこれを必要とした理由は、世界が変化しているからです。 バックボーンは、Model#fetch()XHRがサーバーからデータをロードするための主要なメソッドであると想定していますが、WebSocketを使用してさらに多くのことを行っています。 データがクライアントにプッシュされると、.fetchを呼び出すのは冗長であり、データをサイドロードし、トリガーするイベントフックを取得するための適切な方法が必要です。

#setを使用しないのはなぜですか?

@jridgewellは、#setによって属性がダーティになるためです。 setを使ってみて、何が起こるか見てみましょう。

function callback(data_from_server) {
  console.info(data_from_server);
  m = new Backbone.Model(data_from_server);
  m.set('foo', 'what?', {silent: true});
  console.info(m.changedAttributes())
}

実際の結果:

{foo: 'bar'}
{foo: "what?"}

望ましい結果:

{foo: 'bar'}
false

状態がサーバーと同期していない状態に変更された場合はSetで問題ありませんが、サーバーとの同期として状態をマークする方法がないため、Model#resetが必要です。

私はこの機能のために別のモンキーパッチを書くことになりました:

/**
 * Allow for side-loading data from the server, calling the sync event afterwards.
 * <strong i="6">@param</strong> attributes
 * <strong i="7">@param</strong> options
 */
Backbone.Model.prototype.sync_set = function(attributes, options) {
  var attrs = attributes || {};
  if (options.parse) {
    attrs = this.parse(attrs, options) || {}
  }

  this.set(attrs, options);
  this.changed = {};
  this.trigger('sync', this, attributes, options);
  return this;
}
function callback(data_from_server) {
  console.info(data_from_server);
  m = new Backbone.Model(data_from_server);
  m.set('foo', 'what?', {silent: true});
  console.info(m.changedAttributes())
}
{foo: 'bar'}
false

これはおそらく不足しているアイテムも設定解除する必要があります。 Model#set(attributes)がそれを行うかどうかはわかりません。

@lennerdが指摘したように、 clear()続いてset()呼び出すことは、適切なオプションではありません。

1)2つのchangeイベントを発生させ、
2) clear呼び出しでsilent:trueを使用する場合、設定されていない属性の変更イベントは取得されません。

collection.reset()は非常に直感的で、 Modelは同等の方法から本当に恩恵を受けることができると思います。 私はいつもmodel.reset(attrs)を使おうとしていますが、そこにないときはいつもがっかりしています。 :(

私は先に進んで、Backbone.Modelに機能するresetメソッドを追加するための小さな拡張機能を作成しました: Backbone-Model-Reset

同意する-ネイティブに持つと便利です。 clear()が行っていたように、「id」属性を操作せずに属性をリセットする必要がありました。 これがその

@ thesmart 、Model#setは欠落している属性の設定を解除しないため、Model#resetが必要だと思います。

問題をクローズするときに理由を説明する必要があります。 @ akre54がこれを閉じた理由を知りたいのですが。 バックボーンモデルは意図的に原始的であり、非ピニオン化されていますが、Model#resetがないことは、モデルの使用方法についての意見を表しています。 http://backbonejs.org/#Getting-startedから

哲学的には、Backboneは、JavaScriptを使用してWebアプリケーションを構築するときに一般的に役立つデータ構造化(モデルとコレクション)およびユーザーインターフェイス(ビューとURL)プリミティブの最小限のセットを発見する試みです。

私の知る限り、BackboneのデータモデルはRESTと互換性がありません
後にクライアントのサーバー状態を安全にモデル化する方法がないため
モデルが構築されました。 新しいモデルを構築することが、取得する唯一の方法です。
リセットなしの新しい状態。

2016年7月5日(火曜日)に、pgifford [email protected]書きました:

@thesmart https://github.com/thesmart、Model#setは欠落を解除しません
Model#resetが必要だと思うのはそのためです。

問題をクローズするときに理由を説明する必要があります。 私は
@ akre54https ://github.com/akre54がこれを閉じた理由を知りたい。
バックボーンモデルは意図的に原始的で非ピニオン化されていますが、
Model#resetの欠如は、モデルの使用方法についての意見を表しています。 から
http://backbonejs.org/#Getting -started

哲学的には、バックボーンは最小限のセットを発見する試みです
データ構造化(モデルとコレクション)とユーザーインターフェイス(ビューと
URL)Webアプリケーションを構築するときに一般的に役立つプリミティブ
JavaScriptを使用します。


あなたが言及されたのであなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/jashkenas/backbone/issues/3253#issuecomment -230586424、
またはスレッドをミュートします
https://github.com/notifications/unsubscribe/AARJLQ8-BGeV0X_owHVpyPQAdeiMweNMks5qSriDgaJpZM4CTBHH

モデルreset必要だったので、先に進んでBackboneの_spirit_で作成しました。 私はこれをBackboneの個人的な拡張で使用します。

単純な.clear後に.set .clear続くよりも優れています。これは、デフォルトをモデルにマージし、渡された属性が初期化のようにそれらをオーバーライドできるようにするためです。

/**
 * Clears the model's attributes and sets the default attributes.
 * <strong i="10">@param</strong> {Object} attributes to overwrite defaults
 * <strong i="11">@param</strong> {Object} options  to pass with the "set" call.
 * <strong i="12">@return</strong> {Backbone.Model}  this object, to chain function calls.
 */
reset: function(attributes, options) {
    options = _.extend({ reset: true }, options);

    // ensure default params
    var defaults = _.result(this, 'defaults'),
        attrs = _.defaults(_.extend({}, defaults, attributes || {}), defaults);

    // apply
    this._reset(attrs, options);

    // triggers a custom event, namespaced to model in order
    // to avoid collision with collection's native reset event
    // when listening to a collection.
    if (!options.silent) this.trigger('model:reset', this, options);

    return this;
},

/**
 * Private method to help wrap reset with a custom behavior in child
 * classes.
 * <strong i="13">@param</strong>  {Object} attributes to overwrite defaults
 * <strong i="14">@param</strong>  {Object} options  to pass with the "set" call.
 */
_reset: function(attrs, options) {
    this.clear({ silent: true }).set(attrs, options);
},

silent: trueない場合は、カスタムmodel:resetイベントに加えて、変更イベント( changeおよびchange:attribute )をトリガーします。 model:resetイベントのみをトリガーするように簡単にカスタマイズできますが、モデルをリセットするときは常に変更イベントをトリガーする必要があると思います。

lennerd https://github.com/jashkenas/backbone/issues/3253#issuecomment-58789524のソリューションを少し調整しました。

Backbone.Model.prototype.reset = function(attrs, options) {
    var missing = {};
    for (var key in this.attributes) {
        if (key in attrs) continue;
        attrs[key] = undefined;
        missing[key] = true;
    }
    // trigger all change events at the same time
    this.set(attrs, options);
    // remove missing attributes completely
    for (var key in missing) {
        // no silent option here in case  attributes changed again meanwhile (edge case)
        this.unset(key)
    }
    return this;
};
このページは役に立ちましたか?
0 / 5 - 0 評価