AngularJS 양 방향 데이터 바 인 딩 원리 의$watch,$apply,$digest 응용

도입부
이 글 은 AngularJS 초보 자 에 게 쓴 것 입 니 다.AngularJS 의 양 방향 데이터 연결 에 대해 깊이 알 고 있다 면 소스 코드 를 직접 읽 으 세 요.
배경
AngularJS 개발 자 들 은 양 방향 데이터 연결 이 어떻게 이 루어 졌 는 지 알 고 싶 어 합 니 다.data-binding 과 관련 된 용어 들 이 가득 합 니 다.$watch,$apply,$digest,dirty-checking 등 은 어떻게 일 합 니까?우리 처음부터 이야기 합 시다.
AngularJS 의 양 방향 데이터 바 인 딩 은 브 라 우 저 에 의 해 강요 되 었 습 니 다.
브 라 우 저 는 매우 아름 다 워 보이 지만 사실은 데이터 상호작용 이라는 부분 에서 브 라 우 저의'부작 위'로 인해 브 라 우 저의 데이터 갱신 이 어 려 운 문제 가 되 었 다.구체 적 으로 브 라 우 저 는 하나의 이 벤트 를 쉽게 감청 할 수 있 습 니 다.예 를 들 어 사용자 가 단 추 를 누 르 거나 입력 상자 에 물건 을 입력 할 수 있 습 니 다.이 를 위해 이벤트 리 셋 함수 의 API 를 제공 합 니 다.이벤트 리 셋 함 수 는 자바 script 해석 기 에서 실 행 됩 니 다.그러나 반대로 이렇게 간단 하지 않 습 니 다.만약 에 배경 에서 온 데이터 가 변화 하면 브 라 우 저 에 게 알려 주 고 브 라 우 저 를 새로 고침 시 켜 야 합 니 다.브 라 우 저 는 이런 데이터 인 터 랙 션 체 제 를 제공 하지 않 았 습 니 다.개발 자 에 게 이것 은 넘 기 어 려 운 장애 입 니 다.어떻게 해 야 합 니까?AngularJS 가 나 타 났 습 니 다.$scope 를 통 해 양 방향 데이터 바 인 딩 을 잘 실현 하 였 습 니 다.그 뒤의 원 리 는$watch,$apply,$digest,dirty-checking 입 니 다.
$watch 대기 열($watch list)
말 그대로 watch 는 관찰 이라는 뜻 이다.브 라 우 저 에 무언 가 를 연결 할 때마다$watch 대기 열 에$watch 를 삽입 합 니 다.$watch 를 상상 해 보 세 요.감시 할 수 있 는 model 에 변화 가 있 는 것 입 니 다.예 를 들 어 다음 과 같은 코드 가 있 습 니 다.

User: <input type="text" ng-model="user" />
Password: <input type="password" ng-model="pass" />
여기$scope.user 가 있 습 니 다.첫 번 째 입력 상자 에 연결 되 어 있 고$scope.pass 가 있 습 니 다.두 번 째 입력 상자 에 연결 되 어 있 습 니 다.그리고$watch list 에$watch 두 개 를 추가 합 니 다:
controllers.js 파일 을 만 듭 니 다.코드 는 다음 과 같 습 니 다.

app.controller('MainCtrl', function($scope) {
 $scope.foo = "Foo";
 $scope.world = "World";
});
html 파일 에 대응 하 는 index.html 코드 는 다음 과 같 습 니 다.

Hello, {{ World }}
$scope 에 두 개의 물건 을 추가 하 더 라 도 하나의 것 만 UI 에 연결 되 어 있 기 때문에$watch 만 생 성 되 었 습 니 다.다음 예 를 보 세 요.
controllers.js

app.controller('MainCtrl', function($scope) {
 $scope.people = [...];
});
대응 하 는 html 파일 index.html

<ul>
 <li ng-repeat="person in people">
   {{person.name}} - {{person.age}}
 </li>
</ul>
그 러 고 보 니$watch 가 여러 개 생 성 되 었 습 니 다.사람마다 두 개(하나의 name,하나의 age)가 있 고,그 다음 에 ng-repeat 는 하나의 순환 이기 때문에 10 명의 person 은 모두(2*10)+1 이다.즉,21 개의$watch 가 있다 는 것 이다.따라서 브 라 우 저 에 연 결 된 모든 데 이 터 는$watch 를 생 성 합 니 다.네,그럼 이$watch 는 언제 생 성 되 었 습 니까?AngularJS 의 로드 원 리 를 살 펴 보 겠 습 니 다.
AngularJS 의 로드 원리:
AngularJS 의 템 플 릿 로드 는 컴 파일(copile)과 링크(linking)두 단계 로 나 뉘 며,linking 단계 에서 AngularJS 해석 기 는 각 directive 를 찾 아 필요 한$watch 를 생 성 합 니 다.참,$watch 는 이 단계 에서 생 성 되 었 습 니 다.
이제$digest 를 사용 하기 시 작 했 습 니 다.
$digest 순환
말 그대로 digest 는'소화'라 는 뜻 으로 이름 이 이상 하 다 는 느낌 이 듭 니 다.신기 한 것 은 dirty-checking 입 니 다.말 그대로'더러 운 검사'라 는 뜻 입 니 다.번역 하지 않 는 것 이 좋 습 니 다.원작 자의 본 의 는 틀림없이 이런 뜻 이 아니 라,단지 말로 전 할 수 없 을 뿐이다!
$digest 는 순환 입 니 다.순환 해서 무엇 을 합 니까?$digest 는 우리 의$watch 를 옮 겨 다 니 고 있 습 니 다.$digest 는 하나씩$watch 에 게 물 었 다."어이,네가 관찰 한 데이터 에 변화 가 생 겼 니?"
이것 이 바로 이른바 dirty-checking 이다.모든$watch 검사 가 끝 났 으 니$watch 업데이트 가 있 습 니까?최소한 하나의 업데이트 가 있 으 면 이 순환 은 모든$watch 가 변 하지 않 을 때 까지 다시 실 행 됩 니 다.이렇게 하면 모든 모델 이 더 이상 변 하지 않 을 것 을 보장 할 수 있다.10 회 이상 순환 하면 무한 순환 이 일어나 지 않도록 이상 을 던 질 수 있다 는 것 을 기억 하 라.$digest 순환 이 끝 날 때 DOM 은 상응 하 게 변 합 니 다.
세그먼트 코드 보기,예:controllers.js

app.controller('MainCtrl', function() {
 $scope.name = "Foo";
 $scope.changeFoo = function() {
   $scope.name = "Bar";
 }
});
대응 하 는 html 파일,index.html

{{ name }}
<button ng-click="changeFoo()">Change the name</button>
여 기 는$watch 만 있 습 니 다.ng-click 은$watch 를 만 들 지 않 기 때 문 입 니 다.(함 수 는 변 하지 않 습 니 다.)
$digest 가 실행 하 는 프로 세 스 는:
  • 브 라 우 저 에서 단 추 를 누 르 기;
  • 4.567917.브 라 우 저 는 하나의 이 벤트 를 받 아 angular context 에 들 어 갑 니 다$digest 순환 이 시작 되 었 습 니 다.$watch 마다 변화 하 는 지 확인 하 십시오
  • $scope.name 의$watch 가 변 화 를 보 고 했 기 때문에$digest 순환 을 강제로 다시 실행 합 니 다
  • 새로운$digest 순환 에 변화 가 감지 되 지 않 았 습 니 다.이 때 브 라 우 저 는 제어 권 을 되 찾 아$scope.name 새 값 과 해당 하 는 부분의 DOM 을 업데이트 합 니 다
  • AngularJS 의 뚜렷 한 부족 함 을 알 수 있 습 니 다.angular context 에 들 어 가 는 모든 사건 은$digest 순환 을 실행 합 니 다.알파벳 하나만 입력 하 더 라 도$digest 는 전체 페이지 의 모든$watch 를 옮 겨 다 닙 니 다.
    $apply 적용
    Angular context 는 전체 Angular 의 컨 텍스트 이 고 Angular 용기 로 이해 할 수 있 습 니 다.그렇다면 누가 어떤 사건 이 Angular Context 에 들 어 갈 수 있 고 어떤 사건 이 들 어 갈 수 없 는 지 결정 합 니까?컨트롤 러 는$apply 에 있 습 니 다.
    이벤트 가 실 행 될 때$apply 를 호출 하면 angular context 에 들 어가 고 호출 되 지 않 으 면 들 어가 지 않 습 니 다.방금 예 가$apply 를 호출 하지 않 았 는데 어떻게 된 일 입 니까?라 고 물 을 수 있 습 니 다.Angular 가 뒤에서 해 줬 구나.ng-click 이 있 는 요 소 를 누 르 면$apply 호출 에 이벤트 가 봉 인 됩 니 다.ng-model="foo"입력 상자 가 있 으 면 알파벳 f 를 입력 하면 이벤트 가 이렇게 호출 됩 니 다.$apply("foo="f";").
    $apply 의 응용 장면
    $apply 는$scope 의 함수 입 니 다.호출 하면$digest 순환 을 강제 합 니 다.현재$apply 순환 을 실행 하고 있다 면 이상 을 던 집 니 다.
    브 라 우 저의 데이터 가 제때에 갱신 되 지 않 으 면$scope.$apply()방법 을 호출 하여 강제로 갱신 할 수 있 습 니 다.
    $watch 를 통 해 자신의$scope 를 감시 합 니 다.
    
    <!DOCTYPE html>
    <html ng-app="demoApp">
    <head>
     <title>test</title>
     <!-- Vendor libraries -->
      <script src="lib/jquery-v1.11.1.js"></script>
      <script src="lib/angular-v1.2.22.js"></script>
      <script src="lib/angular-route-v1.2.22.js"></script>
    </head>
    <body> 
     <div ng-controller="MainCtrl" >
      <input ng-model="name" />
      Name updated: {{updated}} times.
     </div> 
     <script >
      var demoApp = angular.module('demoApp',[]); 
      demoApp.controller('MainCtrl', function($scope) {
      $scope.name = "Angular";
      $scope.updated = -1;
      $scope.$watch('name', function() {
      $scope.updated++;
     });
    });
     </script>
     </body>
    </html>
    코드 설명:
    controller 가$watch 에 실 행 될 때 즉시 호출 되 기 때문에 updated 값 을-1 로 설정 합 니 다.위의 입력 상자 에 입력 문자 가 변 했 을 때 updated 의 값 이 변 하 는 것 을 볼 수 있 고 변 화 된 횟수 를 표시 할 수 있 습 니 다.

    $watch 에서 감지 한 데이터 변화
    작은 매듭
    우 리 는 AngularJS 의 양 방향 데이터 바 인 딩 에 대해 초보적인 인식 을 가지 게 되 었 다.AngularJS 에 있어 서 겉 으로 는 DOM 을 조작 하 는 것 이 매우 간단 하 다.사실은 뒤에$watch,$digest,$apply 세 가지 가 묵묵히 작용 하고 있다.데이터 가 변 했 는 지 확인 하 는 과정 을 두루 훑 어 보 는 것 을 dirty-checking 이 라 고 합 니 다.이 과정 을 알 게 되면 코 웃음 을 치 며 낮은 방법 을 느 낄 수 있 을 것 이다.확실히 DOM 에 2000-3000 개의 watch 가 있 으 면 페이지 의 렌 더 링 속도 가 크게 떨 어 집 니 다.
    이 렌 더 링 의 성능 문 제 는 어떻게 해결 합 니까?ECMAScript 6 가 도래 함 에 따라 Angular 2 는 Object.observe 를 통 해$digest 순환 속 도 를 크게 개선 합 니 다.Angular 팀 이 Angular 2 를 미 처 내 놓 지 못 하 는 이유 일 것 이다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기