$ apply ()와 $ digest ()는 AngularJS의 두 가지 핵심 개념이지만 때로는 혼란 스럽습니다. AngularJS의 작동 방식을 이해하려면 먼저 $ apply () 및 $ digest () 작동 방식을 이해해야합니다. 이 기사는 $ apply ()와 $ digest ()가 무엇인지, 그리고 일상 인코딩에 어떻게 적용되는지 설명하는 것을 목표로합니다.
1. $ apply () 및 $ digest () 탐색
1.1. 양방향 데이터 바인딩 및 $ watch ()를 이해합니다.
AngularJS는 양방향 데이터 바인딩이라는 매우 멋진 기능을 제공하여 코드 작성 방법을 크게 단순화합니다. 데이터 바인딩은 뷰의 데이터가 변경되면 변경 사항이 스코프 데이터로 자동으로 공급되므로 스코프 모델이 자동으로 업데이트됩니다. 마찬가지로, 범위 모델이 변경되면보기의 데이터가 최신 값으로 업데이트됩니다. 그렇다면 Angularjs는 어떻게 이렇게합니까? {{amodel}}과 같은 표현식을 작성하면 AngularJS는 스코프 모델에서 감시자를 설정하며 데이터가 변경 될 때보기를 업데이트하는 데 사용됩니다. 여기서 감시자는 AngularJS로 설정할 감시자와 동일합니다.
$ scope. $ watch ( 'amodel', function (newValue, OldValue) {// dom을 newValue}로 업데이트);$ watch ()로 전달 된 두 번째 매개 변수는 콜백 함수이며, 이는 콜백 함수입니다. 아모델이 변경되면이 콜백 함수가 뷰를 업데이트하기 위해 호출 될 것이라는 것을 이해하기가 어렵지 않지만 여전히 매우 중요한 문제가 있습니다! AngularJS는이 콜백 함수를 언제 호출 해야하는지 어떻게 알 수 있습니까? 다시 말해, Amodel이 변경되었음을 알 때 AngularJS는 어떻게 해당 콜백 함수를 호출 했습니까? 스코프 모델의 데이터가 변경되었는지 확인하기 위해 주기적으로 함수를 실행합니까? 글쎄, 그것이 $ 다이제스트 루프가 들어오는 곳입니다.
$ 다이제스트 루프에서는 감시자가 해고됩니다. 감시자가 트리거되면 AngularJS는 범위 모델을 감지합니다. 변경되면 감시자와 관련된 콜백 기능이 호출됩니다. 그렇다면 다음 질문은 $ Digest 루프가 언제 다양한 방식으로 시작됩니까?
$ scope. $ digest ()를 호출 한 후 $ 다이제스트 루프가 시작됩니다. NG 클릭 지시문에 해당하는 핸들러 기능의 범위에서 데이터를 변경한다고 가정하면 AngularJS는 $ digest ()를 호출하여 $ 다이제스트 루프를 자동으로 트리거합니다. $ 다이제스트 루프가 시작되면 각 감시자를 트리거합니다. 이 감시자들은 범위의 현재 모델 값이 지난번 계산 된 모델 값과 다른지 확인합니다. 다른 경우 해당 콜백 함수가 실행됩니다. 이 기능을 호출 한 결과는보기 (번역기 주 : {{amodel}})에서 표현식의 내용이 업데이트된다는 것입니다. NG-Click 지시문 외에도 모델 (예 : NG 모델, $ 타임 아웃 등)을 변경하고 $ 다이제스트 루프를 자동으로 트리거 할 수있는 다른 내장 지시 및 서비스가 있습니다.
지금까지 나쁘지 않습니다! 그러나 작은 문제가 있습니다. 위의 예에서는 AngularJS가 $ digest ()를 직접 호출하지 않지만 $ scope. $ apply ()를 호출하여 $ rootscope를 호출합니다. $ digest (). 따라서 $ 다이제스트 루프는 $ Rootscope에서 시작하여 모든 어린이 스코프 감시자에게 액세스 할 수 있습니다.
참고 : $ scope. $ apply ()는 자동으로 $ rootscope를 호출합니다. $ digest ().
$ apply () 메소드에는 두 가지 양식이 있습니다.
첫 번째는 함수를 매개 변수로 받아들이고 함수를 실행하며 $ 다이제스트 루프를 트리거합니다.
두 번째 유형은 매개 변수를 허용하지 않으며 $ 다이제스트 루프 만 트리거합니다. 첫 번째 형태가 더 나은 이유를 즉시 알 수 있습니다.
1.2. 언제 $ apply () 메소드를 수동으로 호출 할 수 있습니까?
AngularJS가 항상 우리의 코드를 함수로 랩핑하고 $ apply ()를 전달하여 $ digest 루프를 시작하면 언제 $ apply () 메소드를 수동으로 호출해야합니까? 실제로, AngularJS는 이에 대한 매우 명확한 요구 사항을 가지고 있으며, AngularJS 컨텍스트에서 발생하는 변경 사항 (즉, $ apply () 메소드에서 발생하는 모델 변경)에 자동으로 응답 할 책임이 있습니다. 이것은 AngularJS의 내장 지시문이 수행하는 방식이므로 모든 모델 변경이보기에 반영됩니다. 그러나 AngularJS 컨텍스트 외부의 어느 곳에서나 모델을 수정하면 $ apply ()를 수동으로 호출하여 AngularJS에 알려야합니다. AngularJS에게 일부 모델을 수정했다고 말하고 AngularJS가 감시자가 올바르게 응답하도록 도와 줄 수 있기를 바랍니다.
예를 들어, JavaScript에서 settimeout ()를 사용하여 범위 모델을 업데이트하면 AngularJS는 변경 한 내용을 알 수있는 방법이 없습니다. 이 경우 $ apply ()를 호출하고 호출하여 $ 다이제스트 루프를 트리거하는 것은 귀하의 책임입니다. 마찬가지로, DOM 이벤트 리스너를 설정하고 해당 리스너의 일부 모델을 수정하라는 지침이있는 경우, 변경 사항이보기에 올바르게 반영되도록 $ apply ()를 수동으로 호출해야합니다.
예를 살펴 보겠습니다. 가입하면 페이지가로드되면 2 초 후에 메시지를 표시하려는 페이지가 있습니다. 구현은 다음과 같습니다.
HTML :
<body ng-app = "myapp"> <div ng-controller = "messagecontroller"> 지연된 메시지 : {{message}} </div> </body>자바 스크립트 :
/ * $ apply () */ angular.module ( 'myApp', []). } $ scope.getMessage ();
이 예제를 실행하면 2 초 후에 콘솔에 업데이트 된 모델이 표시되지만보기가 업데이트되지 않습니다. 아마도 당신은 이미 그 이유를 알고있을 것입니다. 즉, 우리는 $ apply () 메소드를 호출하는 것을 잊었을 것입니다. 따라서 다음과 같이 getMessage ()를 수정해야합니다.
/ * $ apply */angular.module ( 'myApp', []). 컨트롤러 ( 'messagecontroller', function ($ scope) {$ scope.getMessage = function () {settimeout (function () {$ scope. $ scope.message = ' + 3 초. $ scope.message};위의 예를 실행하면 뷰도 2 초 후에도 업데이트됩니다. 유일한 변경 사항은 이제 코드가 $ scope. $ apply ()로 래핑되어 $ rootscope를 자동으로 트리거하여 뷰를 업데이트하도록 트리거됩니다.
참고 : 그건 그렇고, Settimeout () 대신 $ 시간 초과 서비스를 사용해야합니다. 전자는 귀하를 위해 $ apply ()를 호출하므로 수동으로 호출 할 필요가 없습니다.
또한 위의 코드에서 다음과 마찬가지로 모델을 수정 한 후 매개 변수없이 $ apply ()를 수동으로 호출 할 수도 있습니다.
$ scope.getMessage = function () {settimeout (function () {$ scope.message = '2 초 후 페치'; console.log ( 'message :' + $ scope.message); $ scope. $ apply (); //이 트리거 a $ digest}, 2000); };위의 코드는 두 번째 형식의 $ apply (), 즉 매개 변수가없는 양식을 사용합니다. 항상 함수를 매개 변수로 취하는 $ apply () 메소드를 사용해야한다는 점을 기억하는 것이 중요합니다. 함수를 $ apply ()로 전달할 때 기능이 시도해 보면 ... 캐치 블록으로 래핑되므로 예외가 발생하면 예외는 $ ExceptionHandler 서비스로 처리되기 때문입니다.
$ apply ()를 사용하는 상황은 다음과 같습니다.
• 일반적으로 뷰에서 사용할 수있는 Angular가 제공하는 모든 지침을 기반으로 $ apply ()에게 전화 할 수 있습니다. 모든 ng- [이벤트] 지침 (예 : ng-click, ng-keypress)은 $ apply ()에게 전화합니다.
• 또한 일련의 각도 내장 서비스에 의존하여 $ digest ()를 호출 할 수도 있습니다. 예를 들어, $ http 서비스는 XHR 요청이 완료되고 업데이트 반환 값이 트리거 된 후 $ apply ()를 호출합니다.
• 이벤트를 수동으로 처리하거나 타사 프레임 워크 (예 : jQuery, Facebook API)를 사용하거나 settimeout ()를 호출하면 $ apply () 함수를 사용하여 Angular 리턴을 $ 다이제스트 루프로 만들 수 있습니다.
call settimeout () :
<! doctype html> <html ng-app = "myapp"> <head> <title> $ scope. $ apply () usage </title> <meta charset = "utf-8"> <script src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script> </head> <lody> <div id = "div1"ng-controller = "mytext"> <liv> {{text}} <input id = "btn" "Btn" value = "jquery-event"> </input> </div> </div> </body> </html> <script type = "text/javaScript"> var myModule = Angular.Module ( 'myApp', []); myModule.controller ( "mytext", function ($ scope) {$ scope.text = "place"; settimeout (function () {$ scope.text = "값 시간 이후에 설정된 값"; $ scope. $ apply (); 그렇지 않으면 데이터는 인터페이스에 새로 고침 될 수 없음); </스크립트>타사 프레임 워크 (예 : jQuery, Facebook API)를 사용하십시오.
<! docType html> <html ng-app = "myapp"> <head> <title> $ scope. $ apply () usply </title> <meta charset = "utf-8"> <script src = "https://cdn.jsdelivr.net/jquery/3.1.0/0/jquery.min.json.min.jquery src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script> <body> <div id = "div1"ng-controller = "mytext"> <div> {텍스트}} </div> value = "jquery-event"> </input> </div> </div> </body> </html> <script type = "text/javaScript"> var myModule = Angular.Module ( 'myApp', []); myModule.controller ( "mytext", function ($ scope) {$ scope.text = "place";}); $ (function () {$ ( "#btn"). click (function () {var $ scope = $ ( "#btn"). scope (); $ scope.text = "jQuery에서 설정된 값"; $ scope. $ apply ();}) </script>1.3. $ 다이제스트 루프는 몇 번이나 실행됩니까?
$ 다이제스트 루프가 실행되면 감시자는 실행되어 범위의 모델이 변경되었는지 확인합니다. 변경이 발생하면 해당 리스너 기능이 실행됩니다. 여기에는 중요한 문제가 포함됩니다. 리스너 함수 자체가 범위 모델을 수정하면 어떻게됩니까? AngularJS는이 상황을 어떻게 처리합니까?
대답은 $ 다이제스트 루프가 한 번만 실행되지 않는다는 것입니다. 전류 루프가 종료되면 모델이 변경되었는지 확인하기 위해 다른 루프를 실행합니다. 이것은 더러운 검사이며, 이는 리스너 함수가 실행될 때 발생할 수있는 모델 변경을 처리하는 데 사용됩니다. 따라서 $ 다이제스트 루프는 모델이 더 이상 변경되지 않을 때까지 계속 실행되거나 $ 다이제스트 루프가 10 배에 도달합니다. 따라서 리스너 기능의 모델을 가능한 한 수정하지 마십시오.
참고 : 청취자 함수에서 모델이 변경되지 않더라도 $ 다이제스트 루프도 적어도 두 번 실행됩니다. 위에서 논의한 바와 같이, 모델이 변경되지 않도록 한 번 더 실행됩니다.
결론
기억해야 할 가장 중요한 것은 AngularJS가 모델에 대한 수정을 감지 할 수 있는지 여부입니다. 감지 할 수없는 경우 $ apply ()를 수동으로 호출해야합니다.
궁금한 점이 있으면 메시지를 남겨 주시면 편집자가 제 시간에 모든 사람에게 답장을 드리겠습니다. Wulin.com 웹 사이트를 지원해 주셔서 대단히 감사합니다!