수색…


통사론

  • $ scope. $ watch (watchExpression, callback, [deep compare])
  • $ scope. $ digest ()
  • $ 범위. $ 적용 ([exp])

양방향 데이터 바인딩

Angular는 후드 아래서 어떤 마법을 가지고 있습니다. DOM 을 실제 js 변수에 바인딩 할 수 있습니다.

Angular는 변수를 변경 한 후에 호출되는 " 다이제스트 루프 "라는 루프를 사용합니다. DOM을 업데이트하는 콜백을 호출합니다.

예를 들어, ng-model 지시문은 keyup eventListener 를이 입력에 연결합니다.

<input ng-model="variable" />

keyup 이벤트가 발생할 때마다 다이제스트 루프 가 시작됩니다.

어느 시점에서 다이제스트 루프 는이 범위의 내용을 업데이트하는 콜백을 반복합니다.

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

이 예제의 기본적인 생명주기는 각양이 어떻게 작동하는지 요약합니다 (매우 개략적으로).

  1. 각도 스캔 html
    • ng-model 지시문은 생성 keyup 입력에 청취자
    • 범위 내 expression다이제스트주기에 대한 콜백을 추가합니다.
  2. 사용자가 입력과 상호 작용합니다.
    • keyup 수신기가 다이제스트주기를 시작 합니다.
    • 다이제스트 사이클 은 콜백을 호출합니다.
    • 콜백 업데이트 범위

$ digest와 $ watch

이전 예제의 결과를 얻으려면 양방향 데이터 바인딩을 구현하는 두 가지 핵심 기능을 수행 할 수 있습니다.

  • $ digest 는 사용자 상호 작용 후에 호출됩니다 (DOM => 변수 바인딩).
  • $ watch 변수는 변수 변경 후 호출되도록 콜백을 설정합니다 (binding variable => DOM).

참고 : 이것은 실제 각도 코드가 아닌 데모입니다.


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

우리가 필요로하는 두 가지 기능 :

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

이제 우리는이 함수를 사용하여 DOM에 변수를 연결시킬 수 있습니다 (각도는 내장 된 지시문을 사용하여 수행 할 수 있습니다).

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

물론, 실제 구현은 더 복잡하며 바인딩 할 요소 와 사용할 변수 를 지원합니다.

실행중인 예제는 다음에서 찾을 수 있습니다. https://jsfiddle.net/azofxd4j/

$ 범위 트리

이전 예는 단일 HTML 요소를 단일 변수에 바인딩해야 할 때 충분합니다.

실제로 우리는 많은 요소를 여러 변수에 바인딩해야합니다.

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

ng-repeat 5 개 요소를 number 라는 5 개의 변수에 바인딩합니다. 각각의 값은 서로 다릅니다.


각도가이 동작을 달성하는 방법은 별도의 변수가 필요한 각 요소에 별도의 컨텍스트를 사용하는 것입니다. 이 컨텍스트를 범위라고합니다.

각 범위는 DOM에 바인딩 된 변수 인 속성을 포함하고 $digest$watch 함수는 범위의 메서드로 구현됩니다.

DOM은 트리이며 트리의 여러 수준에서 변수를 사용해야합니다.

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

그러나 우리가 보았 듯이, ng-repeat 내의 변수의 컨텍스트 (또는 범위)는 그 위의 컨텍스트와 다릅니다. 이를 해결하기 위해 스코프를 트리 형태로 구현합니다.

각각의 범위는 아이들의 배열을 가지고 있으며, 그 호출 $digest 방법은 그 아이의 모든 실행 $digest 방법.

이 방법은 - 입력을 변경 한 후에 - $digest 는 div의 범위에 대해 호출되고, 그 다음 5 명의 자식에 대해 $digest 가 실행되어 내용을 업데이트합니다.


범위에 대한 간단한 구현은 다음과 같이 보일 수 있습니다.

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

참고 : 이것은 실제 각도 코드가 아닌 데모입니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow