3

サーバーへの呼び出しを保存したいので、現在オプションを使用Model.save()して送信しています。patchchangedAttributes()

属性を削除して、新しい属性を追加したいと考えています。Model.set()/は、上記の/スキームでは使用できないように毎回unset()変更します。changedAttributes()Model.save()patch

Model.set()設定を解除したい値と、設定したい値を設定したオブジェクトを単純に呼び出して渡したいと思いundefinedます。

私ができる方法はありunset()ますset()changedAttributes()?それともchangedAttributes()、一連の操作を組み合わせて を決定しますか?

// Currently
var m = new Backbone.Model({ "foo": "bar" });
m.unset("foo");
console.log(m.changedAttributes()); // { "foo": undefined }
m.set("baz", "bar");
console.log(m.changedAttributes()); // { "baz": "bar" }
console.log(m.attributes); // { "baz": "bar" }

// At this point, how do I get the combination of changed attributes? something like: { "foo": undefined, "baz": "bar" }?
// Is that even possible? Am I doing something horribly wrong?

//================================================================

// What (I think) I want is for Model.set() to remove attributes with values of undefined, so I only have to make one call and changedAttributes() will be pristine. Maybe with a option or something?
var w = new Backbone.Model({ "foo": "bar" });
w.set({ "foo": undefined, "baz": "bar" });
console.log(w.changedAttributes()); // { "foo": undefined, "baz": "bar" }
console.log(w.attributes); // I would like it to be { "baz": "bar" }, "foo" having been removed in the set() call.

//================================================================

// I was trying to avoid processing the objects by hand. I realize that I can do something like the following.
var h = new Backbone.Model({ "foo": "bar" });
var changes = { "foo": undefined, "baz": "bar" };
_.each(changes, function(val, key) {
    if (_.isUndefined(val)) {
        h.unset(key, { "silent": true });
    } else {
        h.set(key, val, { "silent": true });
    }
});
h.trigger('change'); // Trigger a change event after all the changes have been done.
console.log(changes); // { "foo": undefined, "baz": "bar" }
console.log(h.attributes); // { "baz": "bar" }

上記のコードのフィドル: http://jsfiddle.net/clayzermk1/AmBfh/

このトピックについては、約 1 年前にいくつかの議論があったようですhttps://github.com/documentcloud/backbone/pull/879。私が欲しかった機能は、ある時点で存在していたようです。

編集: @dennis-rongo が指摘したように、これは明らかに手動で行うことができます。上記の私の質問を言い換えると、「Backbone では属性を一度に設定/削除できますか?」そうでない場合、その決定の背後にある理論的根拠は何ですか? Derick Bailey は、属性の状態を処理する Backbone.Memento ( https://github.com/derickbailey/backbone.memento ) を作成しました。このシナリオに密接に関連するモデルの状態に関する Backbone には、いくつかの問題があります ( https://github.com /documentcloud/backbone/pull/2360、ある程度関連: https://github.com/documentcloud/backbone/issues/2316、非常に関連: https://github.com/documentcloud/backbone/issues/2301 )。

編集 2:私は手巻きのソリューションを探しているわけではありません。多かれ少なかれ、私が望むことを行うことができます (上記のサンプル コードを参照)。この一般的なシナリオの明確な例を使用して、現在の設計の正当化を探しています-一度に設定および設定解除します。

更新: https://github.com/documentcloud/backbone/issues/2301で、この件についていくつかの会話がありました。現在の実装についての議論を促すために、プル リクエスト ( https://github.com/documentcloud/backbone/pull/2368 ) を送信しました。

回答を投稿してくれたすべての人に感謝します!

4

3 に答える 3

0

set()現在の実装では、設定および設定解除する混合属性を持つオブジェクトを呼び出して渡すことができます。アトリビュートを効果的に設定解除するには、アトリビュートに の値を割り当てますundefined。キーはモデルのattributesハッシュに残りますが、モデルが JSON にシリアル化されるときはいつでも、undefined値はシリアル化に存在しません (これは の実装によるものですJSON.stringify())。deleteモデルの属性ではありません。

シリアル化で値をJSON.stringify()削除する動作はMDN - JSON - stringifyで説明されています:undefined

未定義、関数、または XML 値が変換中に検出された場合、それらは省略されるか (オブジェクトで見つかった場合)、null に打ち切られます (配列で見つかった場合)。

特定のケース (BSON) では JSON シリアライゼーションを使用していなかったので、自分でソリューションを手作業でコーディングする必要がありました。

プルリクエストで GitHub で議論を始めたところ、最終的には API をそのままにしておくという決定が下されました。詳細については、https://github.com/documentcloud/backbone/pull/2368 のプル リクエストを参照してください

SO と GH の両方について、ディスカッションに参加してくれたすべての人に改めて感謝します。

于 2013-04-05T18:12:11.057 に答える
0

このようなものがうまくいくはずです。

基本的に、unset無効なすべての属性とプロパティ (偽の非ブール値) をループします。

/** Create a Model and set attributes */
var President = Backbone.Model.extend({});
var m = new President({first: 'Abraham', last: 'Lincoln', age: 90});

/** Blank out an attribute or two */
m.set({age: ''});

/** Loop through each attributes and unset falsy ones.  
    Also pass in silent = true so it doesn't trigger a change event 
       (in case you have listeners).
*/
_.each(m.toJSON(), function(val, col){
   if (typeof val !=='boolean' && !val) {
       m.unset(col, {silent: true});
   }
}, this);

/** Output the new Model */
console.log(m.toJSON());

また

Modelその方向に進みたい場合は、変更された属性のみを含む新しいを作成できます。

var President = Backbone.Model.extend({});
var m = new President({
    first: 'Abraham', last: 'Lincoln', age: 90, registered: true});

/** Blank out or change an attribute or two */
m.set({first: null});

/** Pass changed attributes to a new Model */
var t = new President();
if (!_.isEmpty(m.changedAttributes())) {
    _.each(m.changedAttributes(), function(val, col) {
        t.set(col, val);
   }, this);
}
于 2013-03-12T00:49:19.353 に答える