2016-04-30 11 views
6

Ich lerne immer noch angularjs und ich habe ein Problem mit Verständnis Unterschied zwischen $scope und model Objekt und das blockiert mich derzeit zu organisieren (verwenden Sie einige Best Practice) meine App.
Wie ich es verstehe $scope sollte nur gelesen werden (sah einige Tutorials, wo ich das hörte).

Also, wenn ich App laden, sollte ich service verwenden, um einige Daten aus der Datenbank zu erhalten und in model zu speichern.

UPDATE

Gerade jetzt alle Daten, die ich vom Server erhalten werden Controller $ Umfang gespeichert und ich versuche, es zu Diensten zu bewegen und Controller dümmer machen.
Ich überprüfe auch diese article und ich versuche, zweite oder dritte Option zu verwenden, aber immer noch nicht den besten Weg finden, um es zu implementieren.
Das ist mein Service und Controller:Wo in der angularJS App das Modell gespeichert werden soll?

function dataService($http) { 
     var service = { 
      getToDoList: getToDoList, 
      getToDoListByType: getToDoListByType, 
      getToDoById: getToDoById 
     }; 

     return service; 

     function getToDoList() { } 
     function getToDoListByType() { } 
     function getToDoById() { } 
    } 
function toDoController($location) {  
     var vm = this; 

     vm.todos = []; 
     vm.title = 'toDoController'; 

     activate(); 

     function activate() { 
      return getToDos().then(function() { 
       console.log("ToDos loaded"); 
      }); 
     } 

     function getToDos() { 
      return dataservice.getToDoList() 
       .then(function (data) { 
        vm.todos = data; 
        return vm.todos; 
       }); 
     } 
    } 

Aber in dieser Implementierung Liste zu tun ist, wieder in der Steuerung.

Wo sollte ich diese Liste speichern, nachdem ich sie vom Server bekommen habe und wo sie eingestellt werden sollte (vom Controller oder vom Dienst), damit ich diese Liste im Cache bearbeiten kann (lokal bleiben und gelegentlich aktualisieren)?
Ich komme aus C# Welt und dort habe ich immer Objekte verwendet (z. B. Benutzer, Produkt, Artikel usw.) füllen Sie diese Objekte in einer Schleife und speichern Sie es in einer Liste. Ich kann keinen Weg finden, wie ich diesen Ansatz auch in eckigen verwenden soll, und wenn ja, sollte das nur Dienst mit Eigenschaften sein?

Ich verwende einen Dienst, um die Liste und einen Dienst CRUD-Funktionen zu enthalten. Wenn ich Daten in $scope von meinem Modell lade, wie später dieser Bereich aktualisiert wird, wenn ein anderer Teil des Codes Daten in meinem Modell ändert?

Die Änderung kann von einem anderen Controller kommen oder zum Beispiel über SignalR aktualisiert werden. Auch als ich hörte, wenn ich Daten auf Sicht aktualisieren, wie $scope sollte nur gelesen werden muss ich den Dienst aktualisieren und wieder wie und wann $scope dann aktualisieren?

Es tut mir leid, wenn meine Frage zu noob ist, aber ich wäre dankbar, wenn jemand mir helfen kann, zu verstehen, wo in eckigen zu halten?

+0

Irgendwann muss die ToDo-Liste im Controller sein oder Sie werden nicht in der Lage sein, daran zu binden. Was Sie abstrahieren möchten, sind die Vorgänge, die den Dienst erreichen. Wenn sich die Serverimplementierung ändert, müssen Sie nur den Datendienst und nicht den Controller ändern. Es hilft auch bei Komponententests, da Sie einen gefälschten Datendienst erstellen können, um gefälschte Daten zurückzugeben. Ich mache das gleiche für das Prototyping, bevor ich irgendeinen Servercode schreibe. – nbering

+0

Im Beispiel von Frage habe ich einen Dienst erstellt, den der abstrakte Server aufruft. Ich gebe ein anderes Beispiel: 'Dienst ruft die Liste auf>> Rückkehrliste zum Controller $ scope'>' zeige es auf Ansicht' => aber jetzt in der Ansicht manipuliere ich dieses Array in Elementen, indem ich jedem Element einige Eigenschaften hinzufüge (Gruppierung) , Farben usw.), die ich hinzufügen muss, um diese Daten anzuzeigen. Und sagen wir, dass ich alle diese Eigenschaften wieder ändern möchte (Schleife erneut ausführen), aber ich brauche Originaldaten, die ich vom Server bekommen habe. Aber als ich die Liste an den Controller zurückgegeben habe, habe ich kein Original-Array mehr. – 1110

+0

Und da ich keinen Server-Anruf mehr machen möchte, weiß ich nicht, was gute Praxis ist - wo dieses Modell zu halten ist. – 1110

Antwort

4

Das Modell wird häufiger in einem Software-Architekturmuster namens Model-View-Controller (MVC) verwendet. Sie können nicht verstehen, wie das Modell funktioniert, ohne das vollständige Muster zu kennen. In diesem Muster wird die Webanwendung in Komponenten aufgeteilt, um Verantwortlichkeiten zu trennen. Ich werde Sie mit einem Beispiel für vollständigen TODO-Code anleiten, um die tatsächliche Verwendung von MVC zu sehen. enter image description here

Modell: Take/manipulieren Sie alle Domain-Daten (häufiger nehmen Sie dies vom Server).Hier erstellen Sie eine klare API, die den Zugriff auf die Daten ermöglicht, die mit den Diensten passieren. In einem Dienst erhalten Sie Daten vom Server, Sie behalten sie im Inneren und als nächstes liefern Sie einige Funktionen, die den Zugriff ermöglichen. Wenn jemand diese Daten benötigt, verwendet er einfach die Injektion, um auf den Dienst zuzugreifen. Stellen Sie sich diese Art von Service als eine Art Singleton-Klasse mit Daten, Get/Set und anderen Methoden vor. Eine Regel lautet: Wenn Sie nicht wissen, wohin etwas geht, geht es eher zum Service. (FULL CODE)

.factory('api', function ($resource) { 
    'use strict'; 

    var store = { 
     //HERE IS THE API 
     todos: [], 

     api: $resource('/api/todos/:id', null, 
      { 
       update: { method:'PUT' } 
      } 
     ), 
     clearCompleted: function()[..] 
     delete: function (todo)[..] 
     get: function() [..] 
     insert: function (todo)[..] 
     put: function (todo)[..] 
    }; 
    return store; 
}) 

Controller: In den Bildern oben können Sie die Steuerung nur sehen einfach erhalten und nicht von Benutzer-Interaktion geben. Controller manipulieren den Dom nicht. Die Daten gehen von der Ansicht (Benutzer) zum Controller, indem sie den Scope verwenden (oder this im Controller verwenden) und später das Modell mit den Funktionen manipulieren, die wir durch den Service (Modell) erhalten. Viele Male lassen wir den Controller als Vermittler agieren, der die Regel von MVC bricht, indem er das Modell abfragt und das Ergebnis an die Ansicht weitergibt, das ist ein anderer Mustername MVP. Eine Regel ist: Ihr Controller immer schlankeren wie möglich sein muss (FULL CODE)

.controller('TodoCtrl', function TodoCtrl($scope, $routeParams, $filter, store) { 
    //store is the model, we make this in app.js 
    //is the result of a factory we make up,and we named "api" 
    var todos = $scope.todos = store.todos; 
    [..] 
    //in html we call removeTODO 
    //<button class="destroy" ng-click="removeTodo(todo)"></button> 
    //We use user interaction to manipulate the model! 
    $scope.removeTodo = function (todo) { 
    store.delete(todo);//we use the api we make 
    }; 
    [..] 

Ausblick:. Wie Sie im Bild sehen können, Modell aktualisiert die Ansicht, nicht die Steuerung. Wie? Mit Direktiven und Filtern. Vorsicht, die Ansicht hat nur die Darstellung der Daten (Datenbindung). Enthält keine komplexe Logik. Ich möchte klar sein, in MVC sollte die Ansicht direkt auf das Modell zugreifen. Richtlinien und Filter liefern diese Funktion. Wenn Sie eine DOM-Manipulation durchführen möchten, müssen Sie eine Direktive (kein Controller) verwenden. . Hinweis: wir die DOM-Manipulation in der Kompilierung und Verbindungsfunktion der Richtlinie setzen, nicht in der Steuerung (FULL CODE1FULL CODE2)

Ich habe Probleme mit dem Verständnis der Unterschied zwischen $ Umfang und Modell Objekt

Scope bezieht sich nur auf das Modell, wie wir sehen, aber ist nicht das Modell! Der Bereich wird auch für die Benutzerinteraktion verwendet, der Controller hängt vom Bereich ab und der Controller hängt vom Modell ab.

so kann ich diese Liste in einem Cache gespeichert Weise manipulieren (es lokal halten und aktualisieren Sie es gelegentlich)?

Es gibt viele Möglichkeiten, dies zu lösen. Regelmäßig verwenden wir Beobachtermuster, aber im Winkel gibt es eine andere Möglichkeit, dies zu tun, die in den meisten Fällen besser ist. Hier ein Beispiel:

angular 
    .module("testApp", []) 
    .service("myDataService", function(){ 
    this.dataContainer = { 
     valA : "car", 
     valB : "bike" 
    } 
    }) 
    .controller("testCtrl", [ 
    "$scope", 
    "myDataService", 
    function($scope, myDataService){ 
     $scope.data = function(){ 
     //you get always the update data and never store tha data 
     //to the controller 
     return myDataService.dataContainer; 
     }; 
    }]); 

Weitere Informationen this überprüfen, hat einige erstaunliche Antworten.

1

Ich habe nicht genau die gleichen Tutorials wie Sie gelesen, aber ich verweise allgemein auf die Angular Style Guide ursprünglich von John Papa mit beträchtlichem Feedback aus der Angular Community veröffentlicht.

Wenn Sie SignalR verwenden, um Ihre Modelle in Echtzeit zu aktualisieren, denke ich, was Sie suchen, ist das Konzept des unidirektionalen Datenflusses. Ich habe dafür keine großartige Ressource, aber ich habe einige Beispiele für SignalR und Angular gesehen, bei denen Sie vielleicht nur nach der Grundidee suchen.

Insgesamt ist das Ziel, Updates vom Server zu Ihrer Anwendung zu haben. Wenn Ihr Controller also einen Wert aktualisiert, wird Ihr Datenmodell nicht vom Controller-Code aktualisiert. Ihre Anwendung sendet einen Schreibvorgang an den Server, und der Server sendet den neuen Wert an die AngularJS-App zurück.

Eckige Versionen vor 1.5 hatte kein Konzept der unidirektionalen Datenbindung. Wenn Sie die 2-Wege-Bindung von ng-model also automatisch verwenden, müssen Sie den Wert, an den Sie binden, im Allgemeinen als temporär behandeln und dann den Status mit a synchronisieren Cache-Wert oder der Server, wenn ein Benutzer mit der Bearbeitung von Daten fertig ist.

Ihre Frage ist ziemlich weit gefasst. Wenn Sie eine spezifischere Antwort oder eine Anleitung wünschen, können Sie einige Informationen darüber angeben, welche Art von Anwendung Sie schreiben und manchmal die Größe der Anwendung (Anzahl der Controller/Funktionen) gibt eine Vorstellung davon, welche Praktiken Ihnen am besten dienen. Einige der Best Practices für sehr große Apps erscheinen als Anti-Patterns für einfache Wochenendprojekt-Apps.

+0

Hallo, ich muss Frage erneut öffnen. Ich habe die Frage aktualisiert, um genauer zu sein. Ich muss meine App für große App einrichten. Und haben Sie keine Art von Mentor darin. Meine aktualisierte Frage enthält Details. – 1110

2

Das Problem: Sie haben einige Remote-Daten. Sie möchten, dass alle Ihre Controller darauf zugreifen können. Sie wollen nicht, dass sie es für sich alleine schaffen.

Eine Möglichkeit, dies in Winkel zu tun: Verwenden Sie einen Service. Dienstleistungen sind alle Einzelstücke. Dies bedeutet, dass Ihre App nur über eine Instanz des Service verfügt und für die gemeinsame Nutzung von Daten verwendet werden kann. Ich habe mir den Link angesehen, den Sie geteilt haben, und unten ist ein Beispiel für den zweiten Vorschlag: "Service ist ein Modell und ein Service".

function dataService($http) { 
    var todos= []; 
    this.getTodos = function() { return todos; }; 

    this.getToDoList= function() { 
     // use $http to get remote data and assign it to todos 
    }; 
} 

Jetzt können Sie tun TodoService.getData() überall Sie es injiziert haben, sagen vielleicht Ihr .run Block, und von da an TodoService.getTodos() die gleichen Daten der Service bekam zuvor zurück.

Alternativ können Sie den Dienst ausschließlich zum Abrufen von Daten und nicht zum Speichern verwenden (dritter Vorschlag Ihrer Verknüpfung). Um dies zu tun, würden Sie nicht var todos im Service speichern, oder haben Sie eine this.getTodos, würden Sie nur die Funktion getData (und andere Daten erhalten Funktionen). Dann würden Sie von jedem Controller TodoService.getData() ausführen, um die allgemeine HTTP-Get-Funktion auszuführen.

Wo soll ich diese Liste zu speichern, nachdem ich es vom Server erhalten und von wo sollte es (von der Steuerung oder vom Dienst) eingestellt werden, so kann ich diese Liste in einen Cache gespeichert Weise manipulieren (es lokal halten und aktualisieren Sie es gelegentlich)

Wenn Sie es im Cache speichern und bearbeiten möchten, möchten Sie Ihre Daten im Service behalten. Ihre Controller erhalten die Daten vom Service. Es gibt eine Reihe von Artikeln auf using services to talk between controllers. Sie sprechen über die Verwendung von $broadcast, um eigene Ereignisse zu senden, so dass ein Update auf einen Controller andere unabhängige Controller aktualisiert.

In beiden Fällen: möchten Sie die todos Liste an $scope in Ihrem Controller binden. Dadurch können Sie den Inhalt in Ihrer Ansicht ausgeben und Winkelmagie wie 2-Wege-Bindung verwenden. In Ihrem Code:

function toDoController($scope, dataService) {  
    $scope.todos = []; 

    activate(); 

    function activate() { 
     return getToDos().then(function() { 
      console.log("ToDos loaded"); 
     }); 
    }; 

    function getToDos() { 
     return dataService.getToDoList() 
      .then(function (data) { 
       $scope.todos = data; 
       return $scope.todos; 
      }); 
    }; 
} 

Dann Ihrer Ansicht nach, können Sie einfach {{todos}} verweisen.

2

Angular ist nicht mit einer rechtmäßigen Methode zum Speichern von Daten.

Einige Projekte, die diese und andere damit zusammenhängende Fragen angesprochen haben:

https://github.com/mgonto/restangular
https://github.com/adrianlee44/ng-backbone
https://github.com/paysavvy/immutable-angular

Was ich in der Vergangenheit getan haben, ist ein models und collections Modul aufzuschreiben, die Daten speichert. Dies sind nur einfache Konstruktoren.

angular 
    .module('app.models', []) 
    .factory('app.models.User', ['$resource', function($resource) { 

    function User(name) { 
     this.name = name; 
    } 

    User.prototype.sayName = function() { 
     console.log(this.name) 
    }; 

    User.prototype.getInfo = function(params) { 
     $resource.get(params).then(res => { 
     this.info = res.data; 
     }); 
    }; 

    return User; 

    }); 

Und dann in Ihrem Blickmodell verbinden Sie die Ansicht ... mit dem Modell!

['app.models.User', function Controller(User) { 
    this.user = new User('bob'); 
}] 

<div> 
    <button ng-click="vm.user.sayName()">say name</button> 
</div> 
Verwandte Themen