it-swarm.com.de

Unterschied zwischen Knockout-View-Modellen, die als Objektliterale deklariert wurden, und Funktionen

In knockout js sehe ich View Models als entweder deklariert:

var viewModel = {
    firstname: ko.observable("Bob")
};

ko.applyBindings(viewModel );

oder:

var viewModel = function() {
    this.firstname= ko.observable("Bob");
};

ko.applyBindings(new viewModel ());

Was ist der Unterschied zwischen den beiden, wenn überhaupt?

Ich habe diese Diskussion in der google group von knockoutjs gefunden, aber es gab mir keine wirklich zufriedenstellende Antwort.

Ich kann einen Grund sehen, warum ich das Modell mit einigen Daten initialisieren wollte, zum Beispiel:

var viewModel = function(person) {
    this.firstname= ko.observable(person.firstname);
};

var person = ... ;
ko.applyBindings(new viewModel(person));

Aber wenn ich das nicht tue, spielt es dann eine Rolle, welchen Stil ich wähle?

193
Kev

Die Verwendung einer Funktion zum Definieren Ihres Ansichtsmodells bietet eine Reihe von Vorteilen.

Der Hauptvorteil besteht darin, dass Sie sofort auf den Wert this zugreifen können, der der zu erstellenden Instanz entspricht. Dies bedeutet, dass Sie Folgendes tun können:

var ViewModel = function(first, last) {
  this.first = ko.observable(first);
  this.last = ko.observable(last);
  this.full = ko.computed(function() {
     return this.first() + " " + this.last();
  }, this);
};

Daher kann Ihre berechnete Observable an den entsprechenden Wert von this gebunden werden, auch wenn sie aus einem anderen Bereich aufgerufen wird.

Mit einem Objektliteral müssten Sie Folgendes tun:

var viewModel = {
   first: ko.observable("Bob"),
   last: ko.observable("Smith"),
};

viewModel.full = ko.computed(function() {
   return this.first() + " " + this.last();
}, viewModel);

In diesem Fall können Sie viewModel direkt in der berechneten Beobachtungsdatei verwenden, diese wird jedoch (standardmäßig) sofort ausgewertet, sodass Sie sie nicht im Objektliteral definieren können, da viewModel nicht definiert ist bis nach dem Objekt Literal geschlossen. Vielen Leuten gefällt es nicht, dass die Erstellung Ihres Ansichtsmodells nicht in einem Aufruf zusammengefasst ist.

Ein weiteres Muster, mit dem Sie sicherstellen können, dass this immer geeignet ist, besteht darin, eine Variable in der Funktion gleich dem entsprechenden Wert von this zu setzen und stattdessen zu verwenden. Das wäre wie folgt:

var ViewModel = function() {
    var self = this;
    this.items = ko.observableArray();
    this.removeItem = function(item) {
         self.items.remove(item);
    }
};

Wenn Sie sich nun im Bereich eines einzelnen Artikels befinden und $root.removeItem, der Wert von this sind tatsächlich die Daten, die auf dieser Ebene gebunden werden (das wäre der Gegenstand). Indem Sie in diesem Fall self verwenden, können Sie sicherstellen, dass es aus dem Gesamtansichtsmodell entfernt wird.

Eine andere Option ist die Verwendung von bind, das von modernen Browsern unterstützt und von KO hinzugefügt wird, wenn es nicht unterstützt wird. In diesem Fall würde es so aussehen:

var ViewModel = function() {
    this.items = ko.observableArray();
    this.removeItem = function(item) {
         this.items.remove(item);
    }.bind(this);
};

Zu diesem Thema und zu vielen Mustern, die Sie untersuchen können (z. B. Modulmuster und Aufdecken von Modulmustern), kann noch viel mehr gesagt werden. Grundsätzlich bietet Ihnen die Verwendung einer Funktion jedoch mehr Flexibilität und Kontrolle darüber, wie das Objekt erstellt wird und wie auf es verwiesen werden kann Variablen, die für die Instanz privat sind.

251
RP Niemeyer

Ich benutze eine andere Methode, obwohl ähnlich:

var viewModel = (function () {
  var obj = {};
  obj.myVariable = ko.observable();
  obj.myComputed = ko.computed(function () { return "hello" + obj.myVariable() });

  ko.applyBindings(obj);
  return obj;
})();

Einige Gründe:

  1. Keine Verwendung von this, was bei Verwendung innerhalb von ko.computed Usw. Zu Verwirrung führen kann
  2. Mein viewModel ist ein Singleton, ich muss nicht mehrere Instanzen erstellen (d. H. new viewModel())
12
paulslater19