Backbone: Fügen Sie Backbone.Model eine "Reset" -Methode hinzu

Erstellt am 31. Juli 2014  ·  22Kommentare  ·  Quelle: jashkenas/backbone

Ich musste einige Daten eines Modells aktualisieren, die vom Server eingingen. Derzeit gibt es zwei Möglichkeiten: Rufen Sie Model.set an oder setzen Sie Model.attributes direkt. Ich wollte nicht, dass Änderungen aufgezeichnet werden, aber ich konnte auch silent da ich die entsprechenden Ansichten zum Aktualisieren benötigte. Also schrieb ich einen Affen-Patch:

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

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

Sie haben sich gefragt, warum Backbone.Model keine Rücksetzmethode wie Backbone.Collection ?

question

Hilfreichster Kommentar

@thesmart , Model # set setzt fehlende Attribute nicht zurück, weshalb ich denke, dass Model # reset notwendig ist.

Es sollte erforderlich sein, beim Schließen eines Problems einen Grund anzugeben. Ich würde gerne wissen, warum @ akre54 dies geschlossen hat. Backbone-Modelle sind absichtlich primitiv und unpopinioniert. Das Fehlen eines Zurücksetzens von Model # drückt jedoch eine Meinung darüber aus, wie Modelle verwendet werden. Von http://backbonejs.org/#Getting -started

Philosophisch gesehen ist Backbone ein Versuch, den minimalen Satz von Grundelementen für Datenstrukturierung (Modelle und Sammlungen) und Benutzeroberfläche (Ansichten und URLs) zu ermitteln, die im Allgemeinen beim Erstellen von Webanwendungen mit JavaScript nützlich sind.

Alle 22 Kommentare

Reset ist eine Notluke, mit der Sie problemlos effizient in großen Mengen rendern können, wenn Sie wissen, dass Sie es benötigen.

Verwenden Sie für Ihren Fall einfach set .

Können Sie festlegen, ohne Attributänderungen zu verschmutzen?

Am 1. August 2014 um 7:28 Uhr schrieb Jeremy Ashkenas [email protected] :

Reset ist eine Notluke, mit der Sie problemlos effizient in großen Mengen rendern können, wenn Sie wissen, dass Sie es benötigen.

Verwenden Sie für Ihren Fall einfach set.

- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an.

Wenn Sie Model.clear() vor Model.set({}) anrufen, funktioniert dies in Ihrem Fall? Auf diese Weise werden die aktuellen Attribute nicht erweitert, sondern ersetzt. Model.clear() unterstützt auch die stille Option, wenn Sie nicht zwei "Änderungs" -Ereignisse für das Modell auslösen möchten.

Ich bin damit einverstanden, dass diese Methode fehlt. Ich dachte auch darüber nach, model.clear() und model.set() zusammen zu verwenden. Dann bin ich auf das Problem gestoßen, dass ich das change -Ereignis jetzt zweimal auslöse.
Die Verwendung der Option silent beim Aufrufen von model.clear() ist keine Option, da ich auch ein change -Ereignis auslösen möchte, wenn eine Eigenschaft nicht festgelegt wird.

Eine model.reset() -Methode würde einen neuen Attribut-Hash verwenden und diesen Hash mit undefined -Werten für alte Attributschlüssel füllen, die im neuen Attribut-Hash nicht vorhanden sind.

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

Wie wäre es mit:

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

Nein, das hilft nicht. Stellen Sie sich vor, Sie haben einen Schlüssel foo im aktuellen Attribut-Hash des Modells, der in dem neuen attrs -Hash, den Sie an model.reset() . Wenn ich mir das change:foo -Ereignis anhöre, wird es nicht mit dem neuen Wert undefined ausgelöst, da wir im stillen Modus model.unset() .

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/

Cool, ich verstehe was du meinst. Ich würde mich wahrscheinlich dafür entscheiden, this.unset(key, options) um this.attributes explizit zu überschreiben, aber das ist nur eine Frage des Austauschs von attrs[key] = void 0; : panda_face:

Verzeihen Sie jede Unwissenheit, die ich zeige, da ich noch relativ neu in backbone.js bin, aber das diskutierte Verhalten klingt nach Model.fetch . Die Beschreibung sagt:

Setzt den Status des Modells vom Server zurück

Es sieht so aus, als ob change Ereignisse immer noch ausgelöst werden, aber das Modell nicht "schmutzig" machen. Gibt es einen Grund, warum dieser Ansatz nicht gewählt werden kann, wenn Sie Attribute basierend auf einer Serverantwort zurücksetzen möchten? Ich würde mir vorstellen, dass dies nur dann der Fall sein kann, wenn sich ein Modell als Nebeneffekt einer anderen Operation ändert. Im Allgemeinen werden solche Nebenwirkungen jedoch als schlechte Programmierung angesehen und sollten nach Möglichkeit vermieden werden. Wenn der Nebeneffekt nicht vermieden werden kann, ist es möglicherweise sinnvoller, anstelle der neuen Modellattribute ein Antwortflag "Modell XYZ aktualisieren" zu senden und fetch jeder solchen Antwort ein

Nochmals, entschuldigen Sie jede Unwissenheit, die ich in diesem Kommentar zeige.

@kolorahl ,

Das OP möchte die aktuellen Modellattribute löschen und einen neuen JSON übergeben, der zu den neuen Attributen des Modells wird. Auf diese Weise wollen wir das Backend nicht wirklich erreichen, wenn wir bereits über JSON verfügen.

Ich stimme @ lupugabriel1 irgendwie mit seiner Clear + Set-Methode zu. Aber ich denke, dies ist eine Funktionalität, die berücksichtigt werden muss. So etwas wie Backbone.Collection # reset

Der Grund, warum ich das brauchte, ist, dass sich die Welt verändert. Backbone geht davon aus, dass Model # fetch () XHR die primäre Methode zum Laden von Daten vom Server ist, aber wir machen viel mehr Dinge mit Websockets. Wenn Daten an den Client gesendet werden, ist es redundant, .fetch aufzurufen, und wir benötigen eine angemessene Möglichkeit, die Daten von der Seite zu laden und dennoch einen Ereignis-Hook zum Auslösen zu erhalten.

Warum benutzt du nicht #set ?

@jridgewell, weil #set die Attribute verschmutzt. Lassen Sie uns versuchen, set zu verwenden und sehen, was passiert:

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())
}

Tatsächliches Ergebnis:

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

Gewünschtes Ergebnis:

{foo: 'bar'}
false

Das Festlegen ist in Ordnung, wenn der Status nicht mehr mit dem Server synchronisiert ist, das Zurücksetzen des Modells jedoch erforderlich ist, da der Status nicht als mit dem Server synchronisiert markiert werden kann.

Am Ende habe ich einen anderen Affen-Patch für diese Funktion geschrieben:

/**
 * 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

Dies muss wahrscheinlich auch fehlende Elemente deaktivieren. Ich bin mir nicht sicher, ob Model # set (Attribute) dies tut.

Wie @lennerd betonte, ist es keine gute Option, clear() gefolgt von set() aufzurufen , da dies der

1) Feuert zwei change Events und
2) Wenn Sie silent:true auf dem clear Anruf, erhalten Sie nicht ändern Ereignisse auf den Attributen , die nicht gesetzt waren.

collection.reset() ist sehr intuitiv und ich denke, dass Model wirklich von einer äquivalenten Methode profitieren könnte. Ich versuche ständig, model.reset(attrs) , immer enttäuscht, wenn es nicht da ist. :(

Ich habe eine kleine Erweiterung erstellt, um Backbone eine funktionierende reset -Methode hinzuzufügen. Modell :

Zustimmen - wäre nützlich, um nativ zu haben. Ich musste nur die Attribute zurücksetzen, ohne das 'id'-Attribut zu beschädigen, wie es clear () tat. Hier ist der Kern davon .

@thesmart , Model # set setzt fehlende Attribute nicht zurück, weshalb ich denke, dass Model # reset notwendig ist.

Es sollte erforderlich sein, beim Schließen eines Problems einen Grund anzugeben. Ich würde gerne wissen, warum @ akre54 dies geschlossen hat. Backbone-Modelle sind absichtlich primitiv und unpopinioniert. Das Fehlen eines Zurücksetzens von Model # drückt jedoch eine Meinung darüber aus, wie Modelle verwendet werden. Von http://backbonejs.org/#Getting -started

Philosophisch gesehen ist Backbone ein Versuch, den minimalen Satz von Grundelementen für Datenstrukturierung (Modelle und Sammlungen) und Benutzeroberfläche (Ansichten und URLs) zu ermitteln, die im Allgemeinen beim Erstellen von Webanwendungen mit JavaScript nützlich sind.

Soweit ich das beurteilen kann, ist das Datenmodell von Backbone nicht mit REST kompatibel
weil es keine Möglichkeit gibt, den Serverstatus auf dem Client nach a sicher zu modellieren
Modell wurde gebaut. Der Bau eines neuen Modells ist der einzige Weg, um zu bekommen
ein neuer Zustand ohne Zurücksetzen.

Am Dienstag, dem 5. Juli 2016, schrieb pgifford [email protected] :

@thesmart https://github.com/thesmart , Model # set fehlt nicht
Attribute, weshalb ich denke, dass Model # Reset notwendig ist.

Es sollte erforderlich sein, beim Schließen eines Problems einen Grund anzugeben. Ich würde
Ich möchte wissen, warum https://github.com/akre54 dies geschlossen hat.
Backbone-Modelle sind bewusst primitiv und unopinioniert
Das Fehlen des Zurücksetzens von Model # drückt eine Meinung darüber aus, wie Modelle verwendet werden. Von
http://backbonejs.org/#Getting -started

Philosophisch gesehen ist Backbone ein Versuch, die minimale Menge von zu entdecken
Datenstrukturierung (Modelle und Sammlungen) und Benutzeroberfläche (Ansichten und
URLs) Grundelemente, die im Allgemeinen beim Erstellen von Webanwendungen nützlich sind
mit JavaScript.

- -
Sie erhalten dies, weil Sie erwähnt wurden.
Antworte direkt auf diese E-Mail und sieh sie dir auf GitHub an
https://github.com/jashkenas/backbone/issues/3253#issuecomment -230586424,
oder schalten Sie den Thread stumm
https://github.com/notifications/unsubscribe/AARJLQ8-BGeV0X_owHVpyPQAdeiMweNMks5qSriDgaJpZM4CTBHH
.

Ich brauchte ein Modell reset und machte es im _spirit_ von Backbone. Ich benutze dies in meiner persönlichen Erweiterung von Backbone.

Es ist besser als ein einfaches .clear gefolgt von einem .set da die Standardeinstellungen wieder im Modell zusammengeführt werden und alle übergebenen Attribute wie bei der Initialisierung überschrieben werden.

/**
 * 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);
},

Es löst Änderungsereignisse ( change und change:attribute ) zusätzlich zum benutzerdefinierten model:reset -Ereignis aus, wenn nicht silent: true . Es könnte leicht angepasst werden, um nur das model:reset -Ereignis auszulösen, aber ich denke, dass die Änderungsereignisse beim Zurücksetzen eines Modells immer ausgelöst werden sollten.

Ich habe die Lösung von Lennerd https://github.com/jashkenas/backbone/issues/3253#issuecomment -58789524 ein wenig optimiert.

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;
};
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen