In Knockout js sehe ich View Models wie folgt 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-Gruppe von knockoutjs gefunden, aber sie hat mir nicht wirklich eine zufriedenstellende Antwort gegeben.
Ich kann einen Grund erkennen, ob 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 mache, spielt es dann eine Rolle, welchen Stil ich wähle?
prototype
(Methoden, die beispielsweise häufig Daten vom Server abrufen und das Ansichtsmodell entsprechend aktualisieren). Sie können sie jedoch offensichtlich immer noch als Eigenschaft eines Objektliteral deklarieren, sodass ich keinen wirklichen Unterschied sehe.Antworten:
Die Verwendung einer Funktion zum Definieren Ihres Ansichtsmodells bietet einige Vorteile.
Der Hauptvorteil besteht darin, dass Sie sofort auf einen Wert zugreifen können, der
this
der erstellten Instanz entspricht. Dies bedeutet, dass Sie Folgendes tun können:So kann Ihr berechnetes Observable an den entsprechenden Wert von gebunden werden
this
, selbst wenn es aus einem anderen Bereich aufgerufen wird.Mit einem Objektliteral müssten Sie Folgendes tun:
In diesem Fall können Sie
viewModel
das berechnete Observable direkt verwenden, es wird jedoch sofort (standardmäßig) ausgewertet, sodass Sie es nicht innerhalb des Objektliteral definieren können, wieviewModel
es erst nach dem Schließen des Objektliterals definiert wird. 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
es immer angemessen ist, besteht darin, eine Variable in der Funktion auf den entsprechenden Wert von zu setzenthis
und sie stattdessen zu verwenden. Das wäre wie folgt:Wenn Sie sich nun im Bereich eines einzelnen Elements befinden und aufrufen
$root.removeItem
, ist der Wert vonthis
tatsächlich die Daten, die auf dieser Ebene gebunden werden (was das Element wäre). Wenn Sie in diesem Fall self verwenden, können Sie sicherstellen, dass es aus dem Gesamtansichtsmodell entfernt wird.Eine andere Option ist die Verwendung
bind
, die von modernen Browsern unterstützt und von KO hinzugefügt wird, wenn sie nicht unterstützt wird. In diesem Fall würde es so aussehen:Zu diesem Thema kann noch viel mehr gesagt werden, und es gibt viele Muster, die Sie untersuchen können (z. B. Modulmuster und Aufdecken von Modulmustern). Die Verwendung einer Funktion bietet Ihnen jedoch mehr Flexibilität und Kontrolle darüber, wie das Objekt erstellt wird und wie Sie darauf verweisen können Variablen, die für die Instanz privat sind.
quelle
self
undthis
sind gleich, so dass beide gleichwertig sind. In der Funktion removeItem wirdself
dies nützlicher, dathis
dies nicht mehr die aktuelle Instanz ist, wenn sie im Kontext eines untergeordneten Elements ausgeführt wird.Ich benutze eine andere Methode, obwohl ähnlich:
Einige Gründe:
this
, was bei Verwendung innerhalb vonko.computed
s usw. Verwirrung stiften kannnew viewModel()
)quelle
My viewModel is a singleton, I don't need to create multiple instances (i.e. new viewModel())
aber es ist nicht klar, was du zu sagenI don't need to create multiple instances
versuchst. Kannst du mehr Gebrauch machen, damit du den Vorteil deines Ansatzes verstehen kannst? dankefunction
ist, dass Sie es mehr als einmal ausführen würden. In meinem Beispiel handelt es sich jedoch um eine sofort aufgerufene anonyme Funktion, sodass sie nur einmal erstellt wird. Es ist dem Objektliteral im obigen Beispiel sehr ähnlich, bietet Ihnen jedoch mehr Isolation