validators $ scope, $ watch 및 $ scope를 어떻게 사용합니까? AngularJS에 $가 적용됩니까?




form angularjs (6)

AngularJS가 어떻게 작동하는지 알고 있어야합니다.

다이제스트주기 및 $ 범위

맨 먼저 AngularJS는 소위 다이제스트주기 라는 개념을 정의합니다. 이 순환은 루프로 간주 될 수 있습니다. AngularJS는 모든 $scope 의해 감시 된 모든 변수에 변경 사항이 있는지 검사합니다. 따라서 컨트롤러에 $scope.myVar 정의되어 $scope.myVar 변수가 감시 대상으로 표시 되면 AngularJS에 루프의 각 반복에서 myVar 의 변경 사항을 모니터링하도록 암시합니다.

자연스런 후속 질문은 다음과 같습니다. $scope 에 연결된 모든 것이 감시되고 있습니까? 다행히도, 아니오. $scope 있는 모든 객체의 변경 사항을 살펴 본다면 신속하게 다이제스트 루프를 평가하여 평가할 수 있으며 성능 문제가 발생할 수 있습니다. 그래서 AngularJS 팀은 $scope 변수를 두 가지 방법으로보고 (아래 참조) 두 가지 방법을 제공했습니다.

$ watch는 $ 범위 변경을 수신하는 것을 돕습니다.

$scope 변수를 감시하는 것으로 선언하는 두 가지 방법이 있습니다.

  1. 템플릿에서 <span>{{myVar}}</span> 표현식을 사용하여
  2. $watch 서비스를 통해 수동으로 추가

광고 1) 이것은 가장 일반적인 시나리오이며 이전에 본 적이 있다고 확신하지만이 배경에서 시계가 생성되었음을 알지 못했습니다. 예,있었습니다! AngularJS 지시문 (예 : ng-repeat )을 사용하면 암시 적 시계를 만들 수도 있습니다.

광고 2) 이것이 자신의 시계 를 만드는 방법입니다. $watch 서비스는 $scope 첨부 된 일부 값이 변경되면 코드를 실행할 수 있도록 도와줍니다. 거의 사용하지 않지만 가끔 도움이됩니다. 예를 들어 'myVar'가 변경 될 때마다 코드를 실행하려면 다음을 수행 할 수 있습니다.

function MyController($scope) {

    $scope.myVar = 1;

    $scope.$watch('myVar', function() {
        alert('hey, myVar has changed!');
    });

    $scope.buttonClicked = function() {
        $scope.myVar = 2; // This will trigger $watch expression to kick in
    };
}

$ apply를 사용하면 변경 사항을 다이제스트주기와 통합 할 수 있습니다.

통합 메커니즘으로 $apply 함수를 생각할 수 있습니다. $scope 객체에 첨부 된 감시 변수를 직접 변경할 때마다 AngularJS는 변경이 발생했음을 알 수 있습니다. 이것은 AngularJS가 이미 이러한 변경 사항을 모니터링 할 수 있기 때문입니다. 프레임 워크가 관리하는 코드에서 발생하면 다이제스트주기가 계속됩니다.

그러나 때때로 AngularJS 외부에서 일부 값변경 하여 변경 사항이 정상적으로 전파 되는지 확인 하려고합니다. 이것을 고려해보십시오. $scope.myVar 값은 jQuery의 $.ajax() 핸들러 내에서 수정됩니다. 이것은 미래의 어떤 시점에서 일어날 것입니다. AngularJS는 jQuery를 기다리라는 지시가 없기 때문에 이러한 일이 일어날 때까지 기다릴 수 없습니다.

이 문제를 해결하기 위해 $apply 가 도입되었습니다. 소화주기를 명시 적으로 시작할 수 있습니다. 그러나 일부 데이터를 AngularJS (다른 프레임 워크와의 통합)로 마이그레이션하는 데만 사용해야하지만 AngularJS가 오류를 발생 시키므로이 방법을 일반 AngularJS 코드와 함께 사용하지 마십시오.

이 모든 것이 DOM과 어떤 관련이 있습니까?

글쎄, 자습서를 다시 따라해야하는데 이제는이 모든 것을 알게되었습니다. 다이제스트주기는 아무 것도 변경되지 않는 한 모든 $scope 첨부 된 모든 감시자를 평가하여 UI와 JavaScript 코드가 동기화 된 상태를 유지하는지 확인합니다. 다이제스트 루프에서 더 이상 변경 사항이 발생하지 않으면 완료된 것으로 간주됩니다.

컨트롤러에 명시 적으로 $scope 객체에 객체를 첨부하거나 뷰에서 직접 {{expression}} 형식으로 객체를 선언하여 객체를 $scope 객체에 연결할 수 있습니다.

나는 이것이 모든 것에 관한 기본적인 지식을 명확히하는 데 도움이되기를 바랍니다.

추가 읽기 :

나는 $scope.$watch 를 사용하는 방법을 이해하지 못한다 $scope.$watch$scope.$apply . 공식 문서는 도움이되지 않습니다.

내가 특별히 이해하지 못하는 것 :

  • 그들은 DOM에 연결되어 있습니까?
  • DOM 변경 사항을 모델로 업데이트하려면 어떻게해야합니까?
  • 둘 사이의 연결 지점은 무엇입니까?

나는 이 튜토리얼을 시도했지만, $watch$apply 대한 이해는 당연하다고 생각한다.

$apply$watch 는 무엇을합니까? 어떻게 적절하게 사용합니까?


AngularJS는이 이벤트 루프를 확장하여 AngularJS context 라는 것을 만듭니다.

$ watch ()

UI에서 뭔가를 바인딩 할 때마다 $watch 목록에 $watch 를 삽입 합니다 .

User: <input type="text" ng-model="user" />
Password: <input type="password" ng-model="pass" />

여기에는 첫 번째 입력에 바인딩 된 $scope.user 가 있고 두 번째 입력에 바인딩 된 $scope.pass 가 있습니다. 이렇게하면 두 개의 $watch es를 $watch list에 추가 합니다 .

템플릿 이 링크 단계에서로드되면 컴파일러는 모든 지시문을 찾고 필요한 모든 $watch 만듭니다.

AngularJS는 $watch , $watchcollection$watch(true) 합니다. 아래는 깊이있는 관찰자 에게서 취한 세 가지를 모두 설명하는 깔끔한 다이어그램입니다.

angular.module('MY_APP', []).controller('MyCtrl', MyCtrl)
function MyCtrl($scope,$timeout) {
  $scope.users = [{"name": "vinoth"},{"name":"yusuf"},{"name":"rajini"}];

  $scope.$watch("users", function() {
    console.log("**** reference checkers $watch ****")
  });

  $scope.$watchCollection("users", function() {
    console.log("**** Collection  checkers $watchCollection ****")
  });

  $scope.$watch("users", function() {
    console.log("**** equality checkers with $watch(true) ****")
  }, true);

  $timeout(function(){
     console.log("Triggers All ")
     $scope.users = [];
     $scope.$digest();

     console.log("Triggers $watchCollection and $watch(true)")
     $scope.users.push({ name: 'Thalaivar'});
     $scope.$digest();

     console.log("Triggers $watch(true)")
     $scope.users[0].name = 'Superstar';
     $scope.$digest();
  });
}

http://jsfiddle.net/2Lyn0Lkb/

$digest loop

브라우저가 AngularJS 컨텍스트로 관리 할 수있는 이벤트를 수신하면 $digest 루프가 실행됩니다. 이 루프는 두 개의 작은 루프로 구성됩니다. 하나는 $evalAsync 큐를 처리하고 다른 하나는 $watch list 처리합니다. $digest 는 우리가 가지고있는 $watch 스트를 반복 할 것입니다.

app.controller('MainCtrl', function() {
  $scope.name = "vinoth";

  $scope.changeFoo = function() {
      $scope.name = "Thalaivar";
  }
});

{{ name }}
<button ng-click="changeFoo()">Change the name</button>

ng-click은 시계를 만들지 않으므로 여기서 $watch 하나뿐입니다.

버튼을 누릅니다.

  1. 브라우저가 AngularJS 컨텍스트로 들어갈 이벤트를 수신합니다.
  2. $digest 루프가 실행되고 모든 $ watch에 변경 사항을 묻습니다.
  3. $ scope.name의 변경 사항을보고 있던 $watch 가 변경 사항을보고 했으므로 또 다른 $digest 루프가 발생합니다.
  4. 새로운 루프는 아무 것도보고하지 않습니다.
  5. 브라우저가 컨트롤을 다시 가져오고 $ scope.name의 새 값을 반영하는 DOM을 업데이트합니다.
  6. 여기서 중요한 것은 AngularJS 컨텍스트에 들어간 모든 이벤트가 $digest 루프를 실행한다는 것입니다. 즉, 입력에 글자를 쓸 때마다 루프는이 페이지의 모든 $watch 를 검사합니다.

$ apply ()

이벤트가 발생하면 $apply 를 호출하면 각도 컨텍스트를 통과하지만 호출하지 않으면 이벤트가 실행됩니다. 그것만큼 쉽습니다. $apply 내부적으로 $digest() 루프를 호출하고 DOM이 새로 업데이트 된 값으로 업데이트되도록 모든 시계에 대해 반복합니다.

$apply() 메소드는 전체 $scope chain에서 관찰자를 트리거하지만 $digest() 메소드는 현재 $scope 와 그 children 에 대해서만 감시자를 트리거합니다. 위의 $scope 객체 중 어느 것도 로컬 변경 사항에 대해 알 필요가 $digest() 사용할 수 있습니다.


이 블로그 는 예제를 작성하고 이해할 수있는 설명으로 모두 포함되었습니다.

AngularJS $scope 함수 $watch(), $digest()$apply() 는 AngularJS의 중심 기능 중 일부입니다. AngularJS를 이해하려면 $watch() , $digest()$apply() 를 이해하는 것이 중요합니다.

보기의 어딘가에서 $ scope 객체의 변수로 데이터 바인딩을 만들면 AngularJS는 내부적으로 "watch"를 만듭니다. 시계는 AngularJS가 $scope object 의 변수에서 변경 사항을 감시한다는 것을 의미 $scope object . 프레임 워크는 변수를 "감시"합니다. 시계는 $scope.$watch() 함수를 사용하여 작성합니다.이 함수는이 텍스트의 뒷부분에서 설명합니다.

애플리케이션의 주요 지점에서 AngularJS는 $scope.$digest() 함수를 호출합니다. 이 함수는 감시 된 모든 변수가 변경되었는지 모든 시계 및 반복을 반복합니다. 감시 대상 변수가 변경되면 해당 리스너 함수가 호출됩니다. 청취자 함수는 필요한 모든 작업을 수행합니다. 예를 들어 HTML 텍스트를 변경하여 감시 된 변수의 새 값을 반영합니다. 따라서 $digest() 함수는 데이터 바인딩을 업데이트하도록 트리거합니다.

대부분 AngularJS는 $ scope. $ watch ()와 $scope.$digest() 함수를 호출하지만, 어떤 상황에서는 직접 호출해야 할 수도 있습니다. 따라서 그들이 어떻게 작동 하는지를 아는 것은 정말로 좋습니다.

$scope.$apply() 함수는 일부 코드를 실행 한 다음 $scope.$digest() 를 호출하여 모든 시계를 검사하고 해당 감시 수신기 함수가 호출되도록합니다. $apply() 함수는 AngularJS를 다른 코드와 통합 할 때 유용합니다.

이 텍스트의 나머지 부분에서는 $watch(), $digest()$apply() 함수에 대해 자세히 설명합니다.

$ watch ()

$scope.watch() 함수는 어떤 변수의 시계를 생성합니다. watch를 등록 할 때 두 개의 함수를 매개 변수로 $watch() 함수에 전달합니다 :

  • 가치 함수
  • 청취자 기능

다음은 그 예입니다.

$scope.$watch(function() {},
              function() {}
             );

첫 번째 함수는 값 함수이고 두 번째 함수는 리스너 함수입니다.

value 함수는 감시되는 값을 반환해야합니다. AngularJS는 시계 함수가 마지막으로 반환 한 값에 대해 반환 된 값을 확인할 수 있습니다. 그런 식으로 AngularJS는 값이 변경되었는지 확인할 수 있습니다. 다음은 그 예입니다.

$scope.$watch(function(scope) { return scope.data.myVar },
              function() {}
             );

이 예제 valule 함수는 $scope 변수 scope.data.myVar 반환합니다. 이 변수의 값이 변경되면 다른 값이 반환되고 AngularJS는 리스너 함수를 호출합니다.

value 함수가 스코프를 매개 변수로 사용하는 방법에 주목하십시오 (이름에 $가 없음). 이 매개 변수를 통해 value 함수는 $scope 및 해당 변수에 액세스 할 수 있습니다. value 함수는 필요하다면 전역 변수를 볼 수도 있지만 대부분 $scope 변수를 보게됩니다.

리스너 함수는 값이 변경된 경우 수행해야하는 작업을 수행해야합니다. 아마도 다른 변수의 내용을 변경하거나 HTML 요소 등의 내용을 설정해야 할 수도 있습니다. 다음은 그 예입니다.

$scope.$watch(function(scope) { return scope.data.myVar },
              function(newValue, oldValue) {
                  document.getElementById("").innerHTML =
                      "" + newValue + "";
              }
             );

이 예제는 HTML 요소의 내부 HTML을 값을 굵게 만드는 b 요소에 포함 된 변수의 새 값으로 설정합니다. 물론 {{ data.myVar } 코드를 사용하여이 작업을 수행 할 수 있지만 이것은 리스너 함수 내부에서 수행 할 수있는 작업의 예일뿐입니다.

$ digest ()

$scope.$digest() 함수는 $scope object 의 모든 시계와 자식 $ scope 객체 (있는 경우 $scope.$digest() 반복합니다. $digest() 가 시계를 반복 할 때 각 시계에 대해 value 함수를 호출합니다. value 함수가 반환 한 값이 마지막으로 호출 된 값과 다른 경우 해당 시계의 리스너 함수가 호출됩니다.

$digest() 함수는 AngularJS가 필요할 때마다 호출됩니다. 예를 들어 버튼 클릭 핸들러가 실행 된 후 또는 AJAX 호출이 반환 된 후 (done () / fail () 콜백 함수가 실행 된 후).

AngularJS가 $digest() 함수를 호출하지 않는 경우가 있습니다. 일반적으로 데이터 바인딩이 표시된 값을 업데이트하지 않는다는 사실을 감지하여이를 감지합니다. 이 경우 $scope.$digest() 호출하면됩니다. 또는 다음 섹션에서 설명 $scope.$apply() 대신 사용할 수도 있습니다.

$ apply ()

$scope.$apply() 함수는 실행되는 매개 변수로 함수를 취하고, 그 후에 $scope.$digest() 가 내부적으로 호출됩니다. 이렇게하면 모든 시계가 검사되고 모든 데이터 바인딩이 새로 고쳐지는 것이 더 쉬워집니다. 다음은 $apply() 예제입니다.

$scope.$apply(function() {
    $scope.data.myVar = "Another value";
});

$apply() 함수에 매개 변수로 전달 된 함수는 $scope.data.myVar 의 값을 변경합니다. 함수가 종료하면 AngularJS는 $scope.$digest() 함수를 호출하여 모든 시계에서 감시 값의 변경 사항을 검사합니다.

$watch() , $digest( ) 및 $apply() 가 어떻게 작동하는지 보여주기 위해 다음 예제를 살펴보십시오.

<div ng-controller="myController">
    {{data.time}}

    <br/>
    <button ng-click="updateTime()">update time - ng-click</button>
    <button id="updateTimeButton"  >update time</button>
</div>


<script>
    var module       = angular.module("myapp", []);
    var myController1 = module.controller("myController", function($scope) {

        $scope.data = { time : new Date() };

        $scope.updateTime = function() {
            $scope.data.time = new Date();
        }

        document.getElementById("updateTimeButton")
                .addEventListener('click', function() {
            console.log("update time clicked");
            $scope.data.time = new Date();
        });
    });
</script>

그의 예는 $scope.data.time 변수를 보간 지시문에 바인딩하여 변수 값을 HTML 페이지에 병합합니다. 이 바인딩은 $scope.data.time variable 에 내부적으로 시계를 생성 $scope.data.time variable .

이 예제에는 또한 두 개의 버튼이 있습니다. 첫 번째 버튼에는 ng-click 리스너가 연결되어 있습니다. 해당 버튼을 클릭하면 $scope.updateTime() 함수가 호출되고 AngularJS는 $scope.$digest() 호출하여 데이터 바인딩이 업데이트되도록합니다.

두 번째 버튼은 컨트롤러 함수 내부에서 표준 자바 스크립트 이벤트 리스너를 가져옵니다. 두 번째 버튼을 클릭하면 해당 청취자 기능이 실행됩니다. 보시다시피 두 버튼의 리스너 함수는 거의 동일하지만 두 번째 버튼의 리스너 함수가 호출되면 데이터 바인딩이 업데이트되지 않습니다. $scope.$digest() 는 두 번째 버튼의 이벤트 리스너가 실행 된 후에 호출되지 않기 때문입니다. 따라서 두 번째 버튼을 클릭하면 $scope.data.time 변수에서 시간이 업데이트되지만 새 시간은 표시되지 않습니다.

이 문제를 해결하기 위해 $scope.$digest() 를 단추 이벤트 리스너의 마지막 줄에 추가 할 수 있습니다.

document.getElementById("updateTimeButton")
        .addEventListener('click', function() {
    console.log("update time clicked");
    $scope.data.time = new Date();
    $scope.$digest();
});

버튼 리스너 함수 안에서 $digest() 를 호출하는 대신 다음과 같이 $apply() 함수를 사용할 수도 있습니다 :

document.getElementById("updateTimeButton")
        .addEventListener('click', function() {
    $scope.$apply(function() {
        console.log("update time clicked");
        $scope.data.time = new Date();
    });
});

$scope.$apply() 함수가 버튼 이벤트 리스너 내부에서 어떻게 호출되는지와 $scope.data.time 변수의 업데이트가 $apply() 함수에 매개 변수로 전달 된 함수 내에서 수행되는 방법에 $scope.data.time 하십시오. $apply() 함수 호출이 끝나면 AngularJS는 $digest() 내부적으로 호출하므로 모든 데이터 바인딩이 업데이트됩니다.


위의 모든 것을 읽고 끝내며 지루하고 졸려서 (미안하지만 사실입니다). 매우 기술적이며 심층적이며 상세하고 건조합니다. 왜 내가 쓰는거야? AngularJS는 방대하기 때문에 많은 상호 연결된 개념으로 인해 누구나 견딜 수 있습니다. 나는 자주 나 자신에게 질문했다. 나는 그들을 이해할만큼 똑똑하지 못하다. 아니! 왜냐하면 소수의 기술 만이 모든 전문 용어를 사용하는 Dummie 언어로 설명 할 수 있기 때문입니다! 좋아요, 시도하겠습니다.

1) 모든 이벤트 중심의 것입니다. (나는 웃음 소리를 듣는다. 그러나 계속 읽어라.)

어떤 이벤트 주도형인지 모르는 경우 페이지에 버튼을 놓으십시오. "클릭"을 사용하여 함수에 연결하십시오. 사용자가 클릭하면 해당 이벤트를 클릭하여 해당 액션을 실행할 수 있습니다. 기능. 또는 SQL Server / Oracle의 "트리거"를 생각해보십시오.

2) $ watch는 "on-click"입니다.

특별한 점은 매개 변수로 두 개의 함수가 필요하다는 것입니다. 먼저 이벤트의 값을 제공하고, 두 번째 값은 고려해야 할 값을가집니다.

3) $ digest는 지칠 줄 모르고 일하는 상사 , bla-bla-bla하지만 좋은 상사입니다.

4) $ apply는 실수로 증명할 때처럼 수동으로하고 싶을 때 사용할 수있는 방법을 제공합니다 (클릭을하지 않으면 강제로 실행합니다).

이제 시각적으로 만들어 보겠습니다. 아이디어를 얻기가 더 쉽도록 그림을 그려보십시오.

레스토랑에서,

- 손님 은 손님 주문을 받아야합니다.

$watch(
  function(){return orders;},
  function(){Kitchen make it;}
);

- 모든 웨이터가 깨어 있는지 확인하기 위해 주위를 돌아 다니는 관리자 . 고객의 변화 징후에 반응합니다. 이것은 $digest()

- OWNER 는 모든 사람들을 요청할 수있는 최고의 힘을 가지고 있습니다. $apply()


$watch , $apply , $digest 및 digest cycles를 포함하는 매우 심층적 인 비디오를 찾았습니다.

다음은 해당 비디오에서 개념을 설명하는 데 사용되는 몇 가지 슬라이드입니다 (위의 링크가 제거되거나 작동하지 않는 경우).

위의 이미지에서 "$ scope.c"는 (마크 업에서) 데이터 바인딩에서 사용되지 않았기 때문에 감시되지 않습니다. 다른 두 개 ( $scope.a$scope.b )가 감시됩니다.

위의 이미지에서 : AngularJS는 각 브라우저 이벤트를 기반으로 이벤트를 캡처하고 다이제스트주기를 수행하며 모든 변경 사항을 감시하고 시계 기능을 실행하고 DOM을 업데이트합니다. 브라우저 이벤트가 아니라면 $apply 또는 $digest 사용하여 다이제스트주기를 수동으로 트리거 할 수 있습니다.

$apply$digest 에 대한 추가 정보 :


AngularJS에서는 모델을 업데이트하고 뷰 / 템플릿은 내장 또는 사용자 정의 지시문을 통해 DOM을 "자동"으로 업데이트합니다.

Scope 메소드 인 $ apply와 $ watch는 DOM과 관련이 없습니다.

Concepts 페이지 (섹션 "런타임")는 $ digest 루프, $ apply, $ evalAsync 큐 및 $ watch리스트에 대한 설명이 있습니다. 다음은이 텍스트에 첨부 된 그림입니다.

일반적으로 컨트롤러와 지시어 (링크 함수 및 / 또는 컨트롤러)는 스코프에 액세스 할 수 있으며, AngularJS가 해당 범위에 대해 평가할 " watchExpression "을 설정할 수 있습니다. 이 평가는 AngularJS가 $ digest 루프 (특히 "$ watch list"루프)에 들어갈 때마다 수행됩니다. 개별 스코프 속성을 볼 수 있고 두 속성을 함께 볼 수있는 함수를 정의 할 수 있으며 배열 길이 등을 볼 수 있습니다.

AngularJS 양방향 데이터 바인딩 (예 : ng-model 사용), $ http 콜백 발생 등등이있는 텍스트 상자에 "AngularJS"가 입력되면 - $ apply가 이미 호출되었으므로 우리는 위 그림에서 "AngularJS"사각형 안에 있습니다. 모든 watchExpressions가 평가됩니다 (더 이상 변경 사항이 감지되지 않을 때까지 한 번 이상 두 번 이상).

"AngularJS 외부"에서 지시문에 bind ()를 사용하면 해당 이벤트가 발생하여 콜백이 호출되거나 jQuery에 등록 된 콜백 호출이 발생합니다. 우리는 여전히 "기본"사각형 안에 있습니다. 콜백 코드가 $ watch가보고있는 것을 수정하면 $ apply를 호출하여 AngularJS 사각형 안으로 들어가 $ digest 루프를 실행하게되므로 AngularJS는 변경 사항을 확인하고 그 마술을 수행합니다.







angularjs-scope