Szukaj…


Składnia

  • $ scope. $ watch (watchExpression, callback, [deep Compare])
  • $ scope. $ digest ()
  • $ scope. $ apply ([exp])

dwukierunkowe wiązanie danych

Angular ma pod swoją maską trochę magii. umożliwia powiązanie DOM z rzeczywistymi zmiennymi js.

Angular używa pętli, zwanej „ pętlą podsumowania ”, która jest wywoływana po każdej zmianie zmiennej - wywołują oddzwanianie, które aktualizują DOM.

Na przykład ng-model dyrektywa przywiązuje keyup EventListener do tego wejścia:

<input ng-model="variable" />

Przy każdym uruchomieniu zdarzenia keyup rozpoczyna się pętla podsumowania .

W pewnym momencie pętla podsumowania przechodzi przez wywołanie zwrotne, które aktualizuje zawartość tego zakresu:

<span>{{variable}}</span>

Podstawowy cykl życia tego przykładu podsumowuje (bardzo Schematycznie), w jaki sposób działa kąt:

  1. Skanowanie kątowe HTML
    • Dyrektywa ng-model tworzy nasłuchiwanie keyup podczas wprowadzania
    • expression wewnątrz zakresu dodaje wywołanie zwrotne do cyklu trawienia
  2. Użytkownik wchodzi w interakcje z danymi wejściowymi
    • nasłuchiwanie keyup rozpoczyna cykl podsumowania
    • cykl skrótu wywołuje wywołanie zwrotne
    • Oddzwanianie aktualizuje zawartość zakresu

$ skrót i $ zegarek

Wdrożenie dwukierunkowego wiązania danych, aby osiągnąć wynik z poprzedniego przykładu, można wykonać za pomocą dwóch podstawowych funkcji:

  • $ digest jest wywoływany po interakcji użytkownika (wiązanie zmiennej DOM =>)
  • $ watch ustawia wywołanie zwrotne, które będzie wywoływane po zmianach zmiennych (powiązanie zmiennej => DOM)

Uwaga: to przykład, a nie rzeczywisty kod kątowy


<input id="input"/>
<span id="span"></span>

Dwie potrzebne nam funkcje:

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() })
}

Teraz moglibyśmy teraz użyć tych funkcji, aby podłączyć zmienną do DOM (angular ma wbudowane dyrektywy, które zrobią to za Ciebie):

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

Oczywiście rzeczywiste implementacje są bardziej złożone i obsługują parametry, takie jak element, z którym należy się powiązać i jaką zmienną użyć

Działający przykład można znaleźć tutaj: https://jsfiddle.net/azofxd4j/

drzewo $ scope

Poprzedni przykład jest wystarczająco dobry, gdy musimy powiązać pojedynczy element HTML z jedną zmienną.

W rzeczywistości - musimy powiązać wiele elementów z wieloma zmiennymi:

<span ng-repeat="number in [1,2,3,4,5]">{{number}}</span>

To ng-repeat wiąże 5 elementów z 5 zmiennymi zwanymi number , z inną wartością dla każdego z nich!


Sposób, w jaki kąt osiąga to zachowanie, polega na zastosowaniu osobnego kontekstu dla każdego elementu, który potrzebuje osobnych zmiennych. Ten kontekst nazywa się zakresem.

Każdy zakres zawiera właściwości, które są zmiennymi powiązanymi z DOM, a funkcje $digest i $watch są zaimplementowane jako metody zakresu.

DOM jest drzewem, a zmiennych należy używać na różnych poziomach drzewa:

<div>
    <input ng-model="person.name" />
    <span ng-repeat="number in [1,2,3,4,5]">{{number}} {{person.name}}</span>
</div>

Ale jak widzieliśmy, kontekst (lub zakres) zmiennych wewnątrz ng-repeat jest inny niż kontekst powyżej. Aby rozwiązać ten problem - kątowe implementuje zakresy jako drzewo.

Każdy zakres ma tablicę elementów podrzędnych, a wywołanie jego metody $digest uruchomi wszystkie metody $digest dziecka.

W ten sposób - po zmianie danych wejściowych - wywoływany jest $digest dla zakresu div, który następnie uruchamia $digest dla swoich 5 elementów potomnych - co zaktualizuje jego zawartość.


Prosta implementacja zakresu może wyglądać następująco:

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() })
}

Uwaga: to przykład, a nie rzeczywisty kod kątowy



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow