Suche…


Die bidirektionale Datenbindung funktioniert nicht mehr

Man sollte bedenken, dass:

  1. Angulars Datenbindung beruht auf der prototypischen Vererbung von JavaScript und unterliegt daher variablen Spiegelungen .
  2. Ein untergeordneter Bereich erbt normalerweise prototypisch von seinem übergeordneten Bereich. Eine Ausnahme von dieser Regel ist eine Direktive, die einen isolierten Geltungsbereich hat, da sie nicht prototypisch erbt.
  3. Es gibt einige Anweisungen, die einen neuen untergeordneten Bereich erstellen: ng-repeat , ng-switch , ng-view , ng-if , ng-controller , ng-include usw.

Dies bedeutet, dass beim Versuch, Daten in zwei Richtungen an ein Primitiv zu binden, das sich in einem untergeordneten Bereich (oder umgekehrt) befindet, die Dinge möglicherweise nicht wie erwartet funktionieren. Hier ist ein Beispiel, wie einfach es ist, AngularJS zu "brechen" .

Dieses Problem kann leicht durch folgende Schritte vermieden werden:

  1. Haben eine "." in Ihrer HTML-Vorlage, wenn Sie Daten binden
  2. Verwenden Sie die controllerAs Syntax, da die Verwendung der Bindung an ein "gepunktetes" Objekt gefördert wird
  3. $ parent kann verwendet werden, um auf übergeordnete scope statt auf untergeordneten scope zuzugreifen. wie in ng-if wir ng-model="$parent.foo" .

Eine Alternative für das Obige besteht darin, ngModel an eine Getter / Setter-Funktion zu binden, die die zwischengespeicherte Version des Modells aktualisiert, wenn sie mit Argumenten aufgerufen wird, oder sie zurückgeben, wenn sie ohne Argumente aufgerufen wird. Um eine Getter / Setter-Funktion zu verwenden, müssen Sie dem Element mit dem Attribut ngModal ng-model-options="{ getterSetter: true }" ngModal und die Getter-Funktion aufrufen, wenn Sie ihren Wert in expression anzeigen möchten ( Arbeitsbeispiel ).

Beispiel

Aussicht:

<div ng-app="myApp" ng-controller="MainCtrl">
    <input type="text" ng-model="foo" ng-model-options="{ getterSetter: true }">
    <div ng-if="truthyValue">
        <!-- I'm a child scope (inside ng-if), but i'm synced with changes from the outside scope -->
        <input type="text" ng-model="foo">
    </div>
    <div>$scope.foo: {{ foo() }}</div>
</div>

Regler:

angular.module('myApp', []).controller('MainCtrl', ['$scope', function($scope) {
    $scope.truthyValue = true;
      
    var _foo = 'hello'; // this will be used to cache/represent the value of the 'foo' model 
      
    $scope.foo = function(val) {
        // the function return the the internal '_foo' varibale when called with zero arguments,
        // and update the internal `_foo` when called with an argument
        return arguments.length ? (_foo = val) : _foo;
    };
}]);

Bewährte Methode : Es ist am besten, Getter schnell zu halten, da Angular diese wahrscheinlich häufiger als andere Teile Ihres Codes ( Referenz ) nennt.

Dinge, die bei der Verwendung von html5Mode zu tun sind

Bei Verwendung von html5Mode([mode]) ist html5Mode([mode]) erforderlich:

  1. Sie geben die Basis-URL für die Anwendung mit einem <base href=""> im Kopf Ihrer index.html .

  2. Es ist wichtig, dass das base Tag vor allen Tags mit URL-Anforderungen steht. Andernfalls kann dies zu diesem Fehler führen - "Resource interpreted as stylesheet but transferred with MIME type text/html" . Zum Beispiel:

    <head>
        <meta charset="utf-8">
        <title>Job Seeker</title>
    
        <base href="/">
    
        <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="/styles/main.css">
    </head>
    
  3. Wenn Sie kein base Tag angeben möchten, konfigurieren Sie $locationProvider , dass kein base Tag erforderlich ist, indem Sie ein Definitionsobjekt mit requireBase:false an $locationProvider.html5Mode() wie requireBase:false :

    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    });
    
  4. Um das direkte Laden von HTML5-URLs zu unterstützen, müssen Sie das serverseitige URL-Umschreiben aktivieren. Aus AngularJS / Developer Guide / Verwenden von $ location

    In diesem Modus müssen Sie die URL auf dem Server neu schreiben. Grundsätzlich müssen Sie alle Links zum Einstiegspunkt Ihrer Anwendung (z. B. index.html ) neu schreiben. Das Erfordern eines <base> -Tags ist auch für diesen Fall wichtig, da Angular zwischen dem Teil der URL, der die Anwendungsbasis ist, und dem Pfad unterscheidet, der von der Anwendung verarbeitet werden soll.

    Eine hervorragende Ressource für das Umschreiben von Beispielen für verschiedene HTTP- Serverimplementierungen finden Sie in den häufig gestellten Fragen - Anleitung: Vorgehensweise: Konfigurieren Sie Ihren Server für die Verwendung von html5Mode . Zum Beispiel Apache

     RewriteEngine on
    
     # Don't rewrite files or directories
     RewriteCond %{REQUEST_FILENAME} -f [OR]
     RewriteCond %{REQUEST_FILENAME} -d
     RewriteRule ^ - [L]
    
     # Rewrite everything else to index.html to allow html5 state links
     RewriteRule ^ index.html [L]
    

    nginx

     server {
         server_name my-app;
    
         root /path/to/app;
    
         location / {
             try_files $uri $uri/ /index.html;
         }
     }
    

    ausdrücken

     var express = require('express');
     var app = express();
    
     app.use('/js', express.static(__dirname + '/js'));
     app.use('/dist', express.static(__dirname + '/../dist'));
     app.use('/css', express.static(__dirname + '/css'));
     app.use('/partials', express.static(__dirname + '/partials'));
    
     app.all('/*', function(req, res, next) {
         // Just send the index.html for other files to support HTML5Mode
         res.sendFile('index.html', { root: __dirname });
     });
    
     app.listen(3006); //the port you want to use
    

7 Todsünden von AngularJS

Nachfolgend finden Sie eine Liste einiger Fehler, die Entwickler häufig während der Verwendung von AngularJS-Funktionen machen, einige erlernte Lektionen und Lösungen für sie.

1. Manipulieren von DOM durch die Steuerung

Es ist legal, muss aber vermieden werden. Controller sind die Stellen, an denen Sie Ihre Abhängigkeiten definieren, Ihre Daten an die Sicht binden und weitere Geschäftslogik erstellen. Sie können das DOM in einem Controller technisch manipulieren. Wenn Sie jedoch dieselbe oder eine ähnliche Manipulation in einem anderen Teil Ihrer App benötigen, ist ein anderer Controller erforderlich. Die bewährte Methode dieses Ansatzes ist also das Erstellen einer Direktive, die alle Manipulationen und die Verwendung der Direktive in Ihrer App umfasst. Daher lässt der Controller die Ansicht intakt und erledigt ihre Aufgabe. In einer Direktive ist die Verknüpfungsfunktion der beste Ort, um das DOM zu bearbeiten. Sie hat vollen Zugriff auf den Geltungsbereich und das Element. Mit einer Direktive können Sie außerdem die Wiederverwendbarkeit nutzen.

link: function($scope, element, attrs) {
    //The best place to manipulate DOM
}

Sie können auf DOM-Elemente in der Verknüpfungsfunktion auf verschiedene Arten zugreifen, z. B. über den Parameter element , die Methode angular.element() oder reines Javascript.

2. Datenbindung in Transclusion

AngularJS ist bekannt für seine bidirektionale Datenbindung. Es kann jedoch vorkommen, dass Ihre Daten nur in einer Richtung in Anweisungen gebunden sind. Stoppen Sie dort, AngularJS ist nicht falsch, aber wahrscheinlich Sie. Richtlinien sind ein wenig gefährlicher Ort, da Kinder- und isolierte Bereiche betroffen sind. Angenommen, Sie haben die folgende Anweisung mit einer Transklusion

<my-dir>
    <my-transclusion>
    </my-transclusion>
</my-dir>

In my-transclusion haben Sie einige Elemente, die an die Daten im äußeren Bereich gebunden sind.

<my-dir>
    <my-transclusion>
        <input ng-model="name">
    </my-transclusion>
</my-dir>

Der obige Code wird nicht korrekt funktionieren. Hier wird durch Transklusion ein untergeordneter Bereich erstellt, und Sie können die Namensvariable richtig abrufen. Die Änderung an dieser Variablen bleibt jedoch erhalten. Sie können also wirklich auf diese Variable als $ parent.name zugreifen . Diese Verwendung ist jedoch möglicherweise nicht die beste Methode. Ein besserer Ansatz wäre das Umschließen der Variablen in ein Objekt. Zum Beispiel können Sie im Controller Folgendes erstellen:

$scope.data = {
    name: 'someName'
}

Dann können Sie in der Transklusion über das Datenobjekt auf diese Variable zugreifen und sehen, dass die bidirektionale Bindung perfekt funktioniert!

<input ng-model="data.name">

Nicht nur bei Transclusions, sondern in der gesamten App ist es eine gute Idee, die Punktnotation zu verwenden.

3. Mehrere Anweisungen zusammen

Es ist eigentlich legal, zwei Anweisungen zusammen innerhalb desselben Elements zu verwenden, sofern Sie sich an die Regel halten: Zwei isolierte Bereiche können nicht auf demselben Element existieren. Im Allgemeinen weisen Sie beim Erstellen einer neuen benutzerdefinierten Direktive einen isolierten Bereich für die einfache Parameterübergabe zu. Wenn man davon ausgeht, dass die Direktiven myDirA und myDirB Geltungsbereiche isoliert haben und myDirC nicht, werden die folgenden Elemente gültig:

<input my-dir-a my-dirc>

Während das folgende Element einen Konsolenfehler verursacht:

<input my-dir-a my-dir-b>

Daher müssen Richtlinien weise verwendet werden, wobei die Anwendungsbereiche zu berücksichtigen sind.

4. Missbrauch von $ emit

$ emit, $ broadcast und $ on, diese arbeiten nach dem Sender-Empfänger-Prinzip. Mit anderen Worten, sie sind ein Kommunikationsmittel zwischen Steuerungen. Beispielsweise gibt die folgende Zeile das "someEvent" von Controller A aus, das vom betreffenden Controller B abgefangen werden soll.

$scope.$emit('someEvent', args);

Und die folgende Zeile fängt das "someEvent"

$scope.$on('someEvent', function(){});

Bisher scheint alles perfekt zu sein. Denken Sie jedoch daran, dass das Ereignis nicht erfasst wird, wenn der Controller B noch nicht aufgerufen wurde. Dies bedeutet, dass sowohl Sender- als auch Empfänger-Controller aufgerufen werden müssen, damit dies funktioniert. Wenn Sie sich also nicht sicher sind, ob Sie $ emit unbedingt verwenden müssen, scheint der Aufbau eines Services der bessere Weg.

5. Missbrauch von $ scope. $ Watch

$ scope. $ watch wird zum Überwachen einer Variablenänderung verwendet. Immer wenn sich eine Variable geändert hat, wird diese Methode aufgerufen. Ein häufiger Fehler ist jedoch das Ändern der Variablen in $ scope. $ Watch. Dies führt zu Unstimmigkeiten und einer unendlichen $ Digest-Schleife.

$scope.$watch('myCtrl.myVariable', function(newVal) {
    this.myVariable++;
});

Stellen Sie in der obigen Funktion sicher, dass Sie keine Operationen mit myVariable und newVal ausführen.

6. Bindungsmethoden für Ansichten

Dies ist eine der tödlichsten Sünden. AngularJS hat eine bidirektionale Bindung. Wenn sich etwas ändert, werden die Ansichten viele Male aktualisiert. Wenn Sie also eine Methode an ein Attribut einer Sicht binden, wird diese Methode möglicherweise hundertmal aufgerufen, was Sie auch beim Debuggen verrückt macht. Es gibt jedoch nur einige Attribute, die für die Methodenbindung erstellt wurden, z. B. ng-click, ng-blur, ng-on-change usw., die Methoden als Parameter erwarten. Angenommen, Sie haben die folgende Ansicht in Ihrem Markup:

<input ng-disabled="myCtrl.isDisabled()" ng-model="myCtrl.name">

Hier überprüfen Sie den deaktivierten Status der Ansicht über die Methode isDisabled. In der Steuerung myCtrl haben Sie:

vm.isDisabled = function(){
    if(someCondition)
        return true;
    else
        return false;
}

Theoretisch mag es richtig erscheinen, technisch wird dies jedoch zu einer Überlastung führen, da die Methode unzählige Male ausgeführt wird. Um dies zu beheben, sollten Sie eine Variable binden. In Ihrem Controller muss die folgende Variable vorhanden sein:

vm.isDisabled

Sie können diese Variable bei der Aktivierung des Controllers erneut initiieren

if(someCondition)
    vm.isDisabled = true
else
    vm.isDisabled = false

Wenn die Bedingung nicht stabil ist, können Sie diese an ein anderes Ereignis binden. Dann sollten Sie diese Variable an die Sicht binden:

<input ng-disabled="myCtrl.isDisabled" ng-model="myCtrl.name">

Nun haben alle Attribute der Ansicht das, was sie erwarten, und die Methoden werden nur dann ausgeführt, wenn sie benötigt werden.

7. Angulars Funktionen nicht verwenden

AngularJS bietet einige Funktionalitäten, die den Code nicht nur vereinfachen, sondern auch effizienter machen. Einige dieser Funktionen sind unten aufgeführt:

  1. angle.forEach für die Schleifen (Achtung, Sie können es nicht "brechen"; Sie können nur verhindern, dass Sie in den Körper gelangen, betrachten Sie hier die Leistung.)
  2. Winkelelement für DOM-Selektoren
  3. angle.copy : Verwenden Sie dies, wenn Sie das Hauptobjekt nicht ändern möchten
  4. Formularvalidierungen sind bereits großartig. Verwenden Sie schmutzige, makellose, berührte, gültige, erforderliche und so weiter.
  5. Verwenden Sie neben dem Chrome-Debugger auch das Remote-Debugging für die mobile Entwicklung.
  6. Und stellen Sie sicher, dass Sie Batarang verwenden . Es ist eine kostenlose Chrome-Erweiterung, mit der Sie Bereiche einfach überprüfen können
  7. .


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow