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:

  1. Hoekige scans html
    • ng-model keyup maakt een keyup luisteraar bij invoer
    • expression in span voegt een callback toe aan de digest-cyclus
  2. 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



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