Zoeken…


Tweezijdige gegevensbinding werkt niet meer

Men moet in gedachten houden dat:

  1. De gegevensbinding van Angular is gebaseerd op de prototypische overerving van JavaScript, dus is het onderworpen aan variabele schaduw .
  2. Een onderliggende scope neemt normaal gesproken prototypisch over van de bovenliggende scope. Een uitzondering op deze regel is een richtlijn die een geïsoleerde reikwijdte heeft, omdat deze niet prototypisch erft.
  3. Er zijn enkele richtlijnen die een nieuwe onderliggende scope creëren: ng-repeat , ng-switch , ng-view , ng-if , ng-controller , ng-include , etc.

Dit betekent dat wanneer u sommige gegevens in twee richtingen probeert te binden aan een primitief dat zich binnen een kindbereik bevindt (of vice versa), dingen mogelijk niet werken zoals verwacht. Hier is een voorbeeld van hoe gemakkelijk AngularJS kan worden " gebroken " .

Dit probleem kan eenvoudig worden vermeden door deze stappen te volgen:

  1. Heb een "." in uw HTML-sjabloon wanneer u bepaalde gegevens bindt
  2. Gebruik controllerAs syntax omdat dit het gebruik van binding aan een "gestippeld" object bevordert
  3. $ ouder kan worden gebruikt om toegang ouder scope variabelen in plaats van kind scope. zoals binnen ng-if we ng-model="$parent.foo" ..

Een alternatief voor het bovenstaande is om ngModel te binden aan een getter / setter-functie die de ngModel van het model bijwerkt met argumenten, of retourneert wanneer deze zonder argumenten wordt aangeroepen. Om een getter / setter-functie te gebruiken, moet u ng-model-options="{ getterSetter: true }" aan het element met het kenmerk ngModal en de getter-functie aanroepen als u de waarde ervan in expressie wilt weergeven ( Werkend voorbeeld ).

Voorbeeld

Visie:

<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>

controller:

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;
    };
}]);

Best Practice : Het is het beste om getters snel te houden omdat Angular ze waarschijnlijk vaker zal aanroepen dan andere delen van uw code ( referentie ).

Dingen om te doen bij het gebruik van html5Mode

Bij gebruik van html5Mode([mode]) is het noodzakelijk dat:

  1. U geeft de basis-URL voor de toepassing op met een <base href=""> in het hoofd van uw index.html .

  2. Het is belangrijk dat de base tag komt vóór elke tags met URL-aanvragen. Anders kan dit de volgende fout veroorzaken: "Resource interpreted as stylesheet but transferred with MIME type text/html" . Bijvoorbeeld:

    <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. Als je geen gebrek aan een specificeren base tag, configure $locationProvider om niet nodig een base tag door het passeren van een definitie object met requireBase:false tot $locationProvider.html5Mode() als volgt uit:

    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    });
    
  4. Om het rechtstreeks laden van HTML5-URL's te ondersteunen, moet u URL-herschrijving op de server inschakelen. Van AngularJS / Handleiding voor ontwikkelaars / $ -locatie gebruiken

    Het gebruik van deze modus vereist URL-herschrijving aan serverzijde, in principe moet u al uw links naar het toegangspunt van uw toepassing herschrijven (bijv. index.html ). Het vereisen van een <base> -tag is ook belangrijk voor dit geval, omdat Angular hiermee onderscheid kan maken tussen het deel van de URL dat de toepassingsbasis is en het pad dat door de toepassing moet worden verwerkt.

    Een uitstekende bron voor het herschrijven van voorbeelden van aanvragen voor verschillende HTTP-serverimplementaties is te vinden in de veelgestelde vragen over de ui-router: Hoe kan ik: Uw server configureren om met html5Mode te werken . Bijvoorbeeld 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;
         }
     }
    

    uitdrukken

     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 Deadly Sins of AngularJS

Hieronder is de lijst van enkele fouten die ontwikkelaars vaak maken tijdens het gebruik van AngularJS-functionaliteiten, enkele geleerde lessen en oplossingen voor hen.

1. DOM manipuleren via de controller

Het is legaal, maar moet worden vermeden. Controllers zijn de plaatsen waar u uw afhankelijkheden definieert, uw gegevens aan de weergave koppelt en verdere bedrijfslogica maakt. U kunt de DOM technisch manipuleren in een controller, maar wanneer u dezelfde of vergelijkbare manipulatie in een ander deel van uw app nodig hebt, is een andere controller nodig. Dus de beste praktijk van deze aanpak is het creëren van een richtlijn die alle manipulaties omvat en de richtlijn in uw hele app gebruiken. Daarom laat de controller het beeld intact en doet het zijn werk. In een richtlijn is de koppelingsfunctie de beste plaats om de DOM te manipuleren. Het heeft volledige toegang tot de scope en het element, dus met behulp van een richtlijn kunt u ook profiteren van herbruikbaarheid.

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

U kunt op verschillende manieren toegang krijgen tot DOM-elementen in de koppelingsfunctie, zoals de parameter element , methode angular.element() of pure Javascript.

2. Gegevensbinding bij transclusie

AngularJS is beroemd met zijn tweerichtingsgegevensbinding. Soms kunt u echter tegenkomen dat uw gegevens slechts in één richting gebonden zijn binnen richtlijnen. Stop daar, AngularJS is niet verkeerd, maar waarschijnlijk jij. Richtlijnen zijn een beetje gevaarlijke plaatsen omdat het gaat om kind- en geïsoleerde scopes. Stel dat u de volgende richtlijn hebt met één transclusie

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

En binnen mijn-transclusie heb je een aantal elementen die gebonden zijn aan de gegevens in de uiterlijke scope.

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

De bovenstaande code werkt niet correct. Hier creëert transclusie een kindbereik en kun je de naamvariabele krijgen, maar elke wijziging die je in deze variabele aanbrengt, blijft daar. U kunt dus echt toegang krijgen tot deze variabele als $ parent.name . Dit gebruik is echter niet de beste methode. Een betere aanpak zou zijn om de variabelen in een object te verpakken. In de controller kunt u bijvoorbeeld het volgende maken:

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

Dan in de transclusie, kunt u toegang krijgen tot deze variabele via 'data' object en zien dat tweerichtingsbinding perfect werkt!

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

Niet alleen in transclusies, maar in de hele app is het een goed idee om de gestippelde notatie te gebruiken.

3. Meerdere richtlijnen samen

Het is eigenlijk legaal om twee richtlijnen samen binnen hetzelfde element te gebruiken, zolang je je aan de regel houdt: twee geïsoleerde scopes kunnen niet op hetzelfde element bestaan. Over het algemeen wijst u bij het maken van een nieuwe aangepaste richtlijn een geïsoleerde scope toe voor het eenvoudig doorgeven van parameters. Ervan uitgaande dat de richtlijnen myDirA en myDirB scopes hebben en myDirC niet, is het volgende element geldig:

<input my-dir-a my-dirc>

terwijl het volgende element consolefouten veroorzaakt:

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

Daarom moeten richtlijnen verstandig worden gebruikt, rekening houdend met de scope.

4. Misbruik van $ emit

$ emit, $ broadcast en $ on, deze werken volgens een zender-ontvanger principe. Met andere woorden, ze zijn een communicatiemiddel tussen controllers. De volgende regel zendt bijvoorbeeld het 'someEvent' uit van controller A, te vangen door de betreffende controller B.

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

En de volgende regel vangt het 'someEvent'

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

Tot nu toe lijkt alles perfect. Maar onthoud dat, als de controller B nog niet wordt aangeroepen, de gebeurtenis niet wordt opgevangen, wat betekent dat zowel zender- als ontvangercontrollers moeten worden aangeroepen om dit te laten werken. Dus nogmaals, als je niet zeker weet of je zeker $ emit moet gebruiken, lijkt het bouwen van een service een betere manier.

5. Misbruik van $ scope. $ Watch

$ scope. $ watch wordt gebruikt voor het bekijken van een variabele verandering. Wanneer een variabele is gewijzigd, wordt deze methode aangeroepen. Een veel voorkomende fout is echter het wijzigen van de variabele binnen $ scope. $ Watch. Dit zal op enig moment inconsistentie en oneindige $ digest-lus veroorzaken.

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

Zorg er dus in de bovenstaande functie voor dat u geen bewerkingen uitvoert op myVariable en newVal.

6. Bindmethoden aan weergaven

Dit is een van de dodelijkste zonden. AngularJS is bindend in twee richtingen en wanneer er iets verandert, worden de weergaven vele malen bijgewerkt. Dus als u een methode aan een kenmerk van een weergave koppelt, kan die methode mogelijk honderd keer worden genoemd, wat u ook gek maakt tijdens het debuggen. Er zijn echter slechts enkele attributen die zijn gebouwd voor methodebinding, zoals ng-click, ng-blur, ng-on-change, enz., Die methoden als paremeter verwachten. Stel bijvoorbeeld dat u de volgende weergave in uw opmaak hebt:

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

Hier controleert u de uitgeschakelde status van de weergave via de methode is uitgeschakeld. In de controller myCtrl hebt u:

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

In theorie lijkt het misschien correct, maar technisch zal dit een overbelasting veroorzaken, omdat de methode talloze keren zal worden uitgevoerd. Om dit op te lossen, moet u een variabele binden. In uw controller moet de volgende variabele bestaan:

vm.isDisabled

U kunt deze variabele opnieuw activeren bij het activeren van de controller

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

Als de toestand niet stabiel is, kunt u dit binden aan een andere gebeurtenis. Vervolgens moet u deze variabele binden aan de weergave:

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

Nu hebben alle kenmerken van de weergave wat ze verwachten en de methoden worden alleen uitgevoerd wanneer dat nodig is.

7. Geen gebruik van de functionaliteiten van Angular

AngularJS biedt geweldig gemak met enkele van zijn functionaliteiten, niet alleen om uw code te vereenvoudigen maar ook om deze efficiënter te maken. Sommige van deze functies worden hieronder vermeld:

  1. angular.forElk voor de lussen ( let op, je kunt niet 'breken', je kunt alleen voorkomen dat je in het lichaam komt, dus overweeg hier prestaties.)
  2. angular.element voor DOM-selectors
  3. angular.copy : gebruik dit wanneer u het hoofdobject niet moet wijzigen
  4. Formuliervalidaties zijn al geweldig. Gebruik vies, ongerept, aangeraakt, geldig, vereist enzovoort.
  5. Gebruik naast Chrome-foutopsporing ook foutopsporing op afstand voor mobiele ontwikkeling.
  6. En zorg ervoor dat je Batarang gebruikt . Het is een gratis Chrome-extensie waarmee u scopes eenvoudig kunt inspecteren
  7. .


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow