2016-07-25 14 views
1

I already asked this question auf einer anderen Website, aber da es kaum Aufmerksamkeit (geschweige denn eine Antwort) bekam, hoffte ich, dass es hier hineinpassen könnte.JavaScript - Clientseitige Trennung von Model und ViewModel?

Ich entwickle Web-Apps mit dem Modell-View-ViewModel Ansatz mit Knockout.js. Nach dem Lesen auf der original introduction of MVVM von John Gossman, erkannte ich, dass mein ViewModel immer die gesamte Logik der App enthält, nicht nur UI-Logik, sondern alles.

Ich habe irgendwo gelesen, dass mit Knockout, das Modell als die Datenbank oder allgemein die Daten auf dem Server betrachtet wird. Aber nach MVC enthält das Modell auch Funktionen, die etwas mit diesen Daten verarbeiten und nicht UI-bezogen sind.

Also fragte ich mich, ob es sinnvoll wäre, ein separates Model-Objekt unabhängig vom ViewModel-Objekt zu haben? Die Idee dahinter wäre, dass das ViewModel nur UI-Logik (wie von Gossman beabsichtigt) enthält und das Modell nur Business-Logik (wie in MVC) enthalten würde, die nichts mit der tatsächlichen View zu tun hat. Beispiel:

var viewModel = { 
    hint: ko.observable("idle"), //text visible in the View 
    buttonClicked: function() { 
     this.hint("doing stuff"); 
     model.doStuff(); 
     this.hint("done"); 
    } 
}; 

var model = { 
    doStuff: function() { 
     //business logic, UI independent 
    } 
}; 

Gibt es eine Empfehlung oder "Best Practice", die aus der MVVM-Musterdefinition abgeleitet werden kann?

+1

Ich kann nicht sagen, ob es als Best Practice betrachtet wird oder ob es von irgendeinem Muster abgeleitet ist, aber diese "Architektur" ist besonders in größeren Projekten sehr praktisch, da die Logik im Modell selbst nur spezifische Funktionalität für das Modell, das wiederholt in mehreren Ansichtsmodellen für verschiedene Zwecke verwendet werden kann. Die Logik für Model und Viewmodel zu trennen, wird definitiv keinen Schaden anrichten. – Martin

+1

Für mich ist es keine Best Practice, es ist fast eine Voraussetzung. Wenn Ihre Logik komplex wird, werden Ihre Ansichtsmodelle unlesbar, wenn Sie Geschäftslogik und UI-Logik nicht teilen. Außerdem erleichtert es das Fehlermanagement, da es Schichten trennt –

Antwort

1

Ich denke, es wird ein wenig unscharf zu versuchen und haben Daten-Only-Modelle von ViewModels getrennt, weil ViewModels 'abgeleiteten' Spalten enthalten und so die Grenze zwischen dem 'Modell' und was die Ansicht in der ' Ansichtsmodell‘

ich verwenden in der Regel Klassen (vergessen, wie man sie klassifizieren) zu encapsulate die Transformationen von realen Server-Side-Modelle auf die Viewmodels meiner Sicht ... einschließlich abgeleiteten Spalten verwenden (zB Fullname = Firstname +‚‘ + LastName), Datentransformationen (zB Datumsformatierung) und Funktionen, die ich zur Manipulation des viewModels zur Verfügung stelle.

Also wirklich, Sie am Ende verschachtelt haben Klassen (jeweils ein "viewModel" in eigener Sache), um komplexe Einheiten zu kapseln und halten Sie die Transformationen/Funktionen zusammen mit den Entitäten organisiert, denen sie zugeordnet sind. Beachten Sie, dass Funktionen, die Arrays bearbeiten, eine Ebene höher als die Entitäten in der Sammlung, die sie ändern, angehängt sind.

So ein Buch sieht Modell etwas aussehen könnte:

MainVM: 
    Authors: observableArray 
    AddAuthor: function 
    RemoveAuthor: function 

Author class: 
    FirstName 
    LastName 
    FullName: (derived) 
    Books: observableArray 
    AddBook: function 
    RemoveBook: function 

Book class: 
    Title 
    ISBN 
    PublishDate (function to format raw date) 

Außerdem UI-Logik (etwas, das DOM Sachen oder JQuery tut, zum Beispiel) nicht überall hier gehört ... aber in benutzerdefiniertem bindingHandlers oder Knockout-Erweiterungen.

0

Ich finde es hilfreicher, an Knockout als sauber zwischen Spezifikation und Implementierung aufgeteilt zu denken. Die HTML-Datei spezifiziert die Anwendung vollständig, sowohl hinsichtlich des Aussehens als auch des Verhaltens. Die Bindungen geben eine Schnittstelle an, die Sie implementieren müssen, damit die Anwendung funktioniert.

Alles auf der JavaScript-Seite - Ihr Ansichtsmodell und alle benutzerdefinierten Bindungen und jeder zugrunde liegende Code - geht über die Implementierung der angegebenen Schnittstelle. Wie Sie die Aufgaben lösen, ist ein Detail der Implementierung. Gute Programmierpraktiken sagen, dass wenn Sie Routinen haben, die an mehreren Stellen nützlich sein können, besonders wenn sie in anderen Projekten nützlich sein könnten, sollten Sie eine Bibliothek von ihnen erstellen. Dies scheint allgemein für die Geschäftslogik zu gelten.