AngularJS
loop doorloop doorlopen
Zoeken…
Syntaxis
- $ scope. $ watch (watchExpression, callback, [diep vergelijken])
- $ Scope. $ Verteren ()
- $ Scope. $ Van toepassing zijn ([EXP])
tweezijdige gegevensbinding
Angular heeft wat magie onder de motorkap. het maakt het mogelijk om DOM te binden aan echte js-variabelen.
Angular gebruikt een lus, de " digest-lus " genaamd, die wordt opgeroepen na elke wijziging van een variabele - callbacks aanroept die de DOM bijwerken.
De ng-model
keyup
voegt bijvoorbeeld een keyup
eventListener toe aan deze invoer:
<input ng-model="variable" />
Elke keer dat de keyup
gebeurtenis wordt gestart, start de digest-lus .
Op een gegeven moment herhaalt de digest-lus een callback die de inhoud van deze reeks bijwerkt:
<span>{{variable}}</span>
De basislevenscyclus van dit voorbeeld vat (heel schematisch) samen hoe hoekig werkt:
- Hoekige scans html
-
ng-model
keyup
maakt eenkeyup
luisteraar bij invoer -
expression
in span voegt een callback toe aan de digest-cyclus
-
- Gebruiker reageert op invoer
-
keyup
luisteraar start digest cyclus - digest-cyclus roept de terugbelactie op
- Callback updates overspannen de inhoud
-
$ digest en $ watch
Het implementeren van tweerichtingsgegevensbinding, om het resultaat van het vorige voorbeeld te bereiken, zou kunnen worden gedaan met twee kernfuncties:
- $ digest wordt genoemd na een gebruikersinteractie (bindende DOM => variabele)
- $ watch stelt een callback in die moet worden aangeroepen na variabele wijzigingen (bindende variabele => DOM)
opmerking: dit is een voorbeeld, een demonstratie, niet de werkelijke hoekcode
<input id="input"/>
<span id="span"></span>
De twee functies die we nodig hebben:
var $watches = [];
function $digest(){
$watches.forEach(function($w){
var val = $w.val();
if($w.prevVal !== val){
$w.callback(val, $w.prevVal);
$w.prevVal = val;
}
})
}
function $watch(val, callback){
$watches.push({val:val, callback:callback, prevVal: val() })
}
Nu kunnen we deze functies gebruiken om een variabele aan te sluiten op de DOM (hoekig wordt geleverd met ingebouwde richtlijnen die dit voor u doen):
var realVar;
//this is usually done by ng-model directive
input1.addEventListener('keyup',function(e){
realVar=e.target.value;
$digest()
}, true);
//this is usually done with {{expressions}} or ng-bind directive
$watch(function(){return realVar},function(val){
span1.innerHTML = val;
});
Natuurlijk zijn de echte implementaties complexer en ondersteunen parameters zoals aan welk element te binden en welke variabele te gebruiken
Een voorbeeld hiervan kan hier worden gevonden: https://jsfiddle.net/azofxd4j/
de $ scope tree
Het vorige voorbeeld is goed genoeg als we een enkel HTML-element moeten binden aan een enkele variabele.
In werkelijkheid moeten we veel elementen binden aan veel variabelen:
<span ng-repeat="number in [1,2,3,4,5]">{{number}}</span>
Deze ng-repeat
bindt 5 elementen aan 5 variabelen die number
, met een verschillende waarde voor elk ervan!
De manier waarop hoekig dit gedrag bereikt, gebruikt een afzonderlijke context voor elk element dat afzonderlijke variabelen nodig heeft. Deze context wordt een scope genoemd.
Elk bereik bevat eigenschappen, dit zijn de variabelen die zijn gebonden aan de DOM, en de functies $digest
en $watch
zijn geïmplementeerd als methoden van het bereik.
De DOM is een boom en variabelen moeten in verschillende niveaus van de boom worden gebruikt:
<div>
<input ng-model="person.name" />
<span ng-repeat="number in [1,2,3,4,5]">{{number}} {{person.name}}</span>
</div>
Maar zoals we zagen, is de context (of het bereik) van variabelen binnen ng-repeat
anders dan de context erboven. Om dit op te lossen, implementeert hoekige scopes een boom.
Elke scope heeft een scala aan kinderen, en roept haar $digest
methode zal van elk van haar kinderen rennen $digest
methode.
Op deze manier wordt - na het wijzigen van de invoer - $digest
opgeroepen voor het bereik van de div, dat vervolgens de $digest
voor zijn 5 kinderen uitvoert - die de inhoud ervan bijwerkt.
Een eenvoudige implementatie voor een scope kan er zo uitzien:
function $scope(){
this.$children = [];
this.$watches = [];
}
$scope.prototype.$digest = function(){
this.$watches.forEach(function($w){
var val = $w.val();
if($w.prevVal !== val){
$w.callback(val, $w.prevVal);
$w.prevVal = val;
}
});
this.$children.forEach(function(c){
c.$digest();
});
}
$scope.prototype.$watch = function(val, callback){
this.$watches.push({val:val, callback:callback, prevVal: val() })
}
opmerking: dit is een voorbeeld, een demonstratie, niet de werkelijke hoekcode