$ Aplicar () y $ Digest () son dos conceptos centrales en Angularjs, pero a veces son confusos. Para comprender cómo funciona AngularJS, primero debe comprender cómo $ aplican () y $ digest () funcionan. Este artículo tiene como objetivo explicar qué aplican $ aplican () y $ digest (), y cómo se aplican en la codificación diaria.
1. Explore $ Aplicar () y $ Digest ()
1.1. Comprender el enlace de datos bidireccional y $ watch ();
AngularJS proporciona una característica muy genial llamada enlace de datos de dos vías, que simplifica enormemente cómo escribimos nuestro código. La unión de datos significa que cuando cambia los datos en la vista, el cambio se volverá a recibir automáticamente a los datos del alcance, lo que significa que el modelo de alcance se actualizará automáticamente. Del mismo modo, cuando cambia el modelo de alcance, los datos en la vista se actualizan al último valor. Entonces, ¿cómo hace esto Angularjs? Cuando escribe una expresión como {{amodel}}, AngularJS establecerá un observador para usted en el modelo de alcance, que se utiliza para actualizar la vista cuando cambia los datos. El observador aquí es lo mismo que el observador que establecerá en Angularjs:
$ Scope. $ Watch ('Amodel', function (NewValue, OldValue) {// Actualizar el DOM con NewValue});El segundo parámetro que pasa a $ watch () es una función de devolución de llamada, que se llamará cuando cambia el valor de Amodel. Cuando Amodel cambia, no es difícil entender que esta función de devolución de llamada se llamará para actualizar la vista, ¡pero todavía hay un problema muy importante! ¿Cómo sabe AngularJS cuándo llamar a esta función de devolución de llamada? En otras palabras, ¿cómo llamó AngularJS la función de devolución de llamada correspondiente cuando sabe que Amodel ha cambiado? ¿Ejecutará una función periódicamente para verificar si los datos en el modelo de alcance han cambiado? Bueno, ahí es donde entra el bucle $ Digest.
En el bucle $ Digest, los observadores serán despedidos. Cuando se activa un observador, AngularJS detectará el modelo de alcance. Si cambia, se llamará a la función de devolución de llamada asociada con el observador. Entonces, la siguiente pregunta es ¿cuándo comienza el bucle $ digest de varias maneras?
Después de llamar a $ alcance. $ Digest (), comienza el bucle $ digest. Suponga que cambia un alcance de datos en la función del controlador correspondiente a una directiva Ng-Click, AngularJS activará automáticamente un bucle de $ Digest llamando a $ digest (). Cuando comienza el bucle $ Digest, desencadena a cada observador. Estos observadores verificarán si el valor del modelo actual en el alcance es diferente del valor del modelo calculado la última vez. Si es diferente, se ejecutará la función de devolución de llamada correspondiente. El resultado de llamar a esta función es que se actualizará el contenido de la expresión en la vista (nota del traductor: como {{amodel}}). Además de la Directiva NG-CLIC, hay algunas otras directivas y servicios incorporados para permitirle cambiar modelos (como Ng-Model, $ TimeOut, etc.) y activar automáticamente un bucle de $ Digest.
¡Hasta ahora no está mal! Sin embargo, hay un pequeño problema. En el ejemplo anterior, AngularJS no llama a $ Digest () directamente, sino que llama $ SCOPE. $ Aplicar (), que llama $ ROOTSCOPE. $ Digest (). Por lo tanto, un bucle de $ Digest comienza en $ Rootscope, que luego accederá a todos los observadores de alcance de los niños.
Nota: $ ACEPE. $ Aplicar () llamará automáticamente $ RootsCope. $ Digest ().
El método $ Aplicar () tiene dos formularios:
El primero aceptará una función como parámetro, ejecutará la función y activará un bucle $ digest.
El segundo tipo no aceptará ningún parámetro y simplemente activará un bucle $ Digest. Veremos de inmediato por qué la primera forma es mejor.
1.2. ¿Cuándo llamar manualmente el método $ aplic ()?
Si AngularJS siempre envuelve nuestro código en una función y pase $ Aplicar () para iniciar un bucle de $ Digest, ¿cuándo necesitamos llamar al método $ Apply () manualmente? De hecho, AngularJS tiene un requisito muy claro para esto, que solo es responsable de responder automáticamente a los cambios que ocurren en el contexto de AngularJS (es decir, cambios en los modelos que ocurren en el método $ Aplicat ()). Así es como lo hace la directiva incorporada de AngularJS, por lo que cualquier cambio de modelo se reflejará en la vista. Sin embargo, si modifica el modelo en cualquier lugar fuera del contexto de AngularJS, debe notificar a AngularJS llamando a $ Aplicar () manualmente. Es como decirle a AngularJS que ha modificado algunos modelos y espera que AngularJS pueda ayudarlo a activar los observadores para que responda correctamente.
Por ejemplo, si usa setTimeOut () en JavaScript para actualizar un modelo de alcance, entonces AngularJS no tiene forma de saber lo que ha cambiado. En este caso, es su responsabilidad llamar a $ Aplicar () y activar un bucle de $ Digest llamándolo. Del mismo modo, si tiene una directiva para establecer un oyente de eventos DOM y modificar algunos modelos en ese oyente, también debe llamar a $ Aplicar () manualmente para garantizar que los cambios se reflejarán correctamente en la vista.
Veamos un ejemplo. Únase a usted, tiene una página que una vez que se carga la página, desea mostrar un mensaje después de dos segundos. Su implementación puede verse así:
HTML:
<Body Ng-App = "MyApp"> <div Ng-Controller = "MessageController"> Mensaje retrasado: {{Message}} </div> </body>JavaScript:
/ * Lo que sucede sin un $ aplic () */ angular.module ('myApp', []). Controller ('MessageController', function ($ scope) {$ scope.getMessage = function () {setTimeOut (function () {$ scope.messess = 'falled después de 3 segundos; } $ scope.getMessage ();Al ejecutar este ejemplo, verá que después de dos segundos, la consola muestra el modelo actualizado, sin embargo, la vista no se actualiza. Tal vez ya sepa la razón, es decir, olvidamos llamar al método $ Aplicat (). Por lo tanto, necesitamos modificar getMessage () de la siguiente manera:
/ * Lo que sucede con $ aplic */angular.module ('myapp', []). Controler ('messageController', function ($ scope) {$ scope.getMessage = function () {setTimeOut (function () {$ scope. $ Aplicar (function () {// envolvió esto dentro de $ $ scope.message = 'fetched después de 3 segundos. $ scope.message);Si ejecuta el ejemplo anterior, verá que la vista también se actualizará después de dos segundos. El único cambio es que nuestro código ahora está envuelto en $ alcance. $ Aplicar (), que activará automáticamente $ ROOTSCOPE. $ Digest (), de modo que los observadores se activan para actualizar la vista.
Nota: Por cierto, debe usar el servicio $ TimeOut en lugar de SetTimeOut (), porque el primero llamará a $ Aplicar () para usted, por lo que no necesita llamarlo manualmente.
Además, tenga en cuenta que en el código anterior, también puede llamar manualmente $ Aplicar () sin parámetros después de modificar el modelo, al igual que el siguiente:
$ scope.getMessage = function () {setTimeOut (function () {$ scope.message = 'fetched después de dos segundos'; console.log ('mensaje:' + $ scope.message); $ scope. $ apply (); // Esto desencadena un $ digest}, 2000); };El código anterior utiliza la segunda forma de $ Aplication (), es decir, el formulario sin parámetros. Es importante recordar que siempre debe usar el método $ Aplicat () que toma una función como parámetro. Esto se debe a que cuando pasa una función a $ Aplicar (), la función se envolverá en un bloque de captura Prueba, por lo que una vez que ocurra una excepción, la excepción se procesará mediante el servicio $ ExceptionHandler.
La situación de usar $ Aplicar () es la siguiente:
• Por lo general, puede llamar a $ Aplicar () según cualquier directiva proporcionada por Angular que pueda usarse en la vista. Todas las directivas NG- [Evento] (como Ng-Click, Ng-KeyPress) llamará a $ Aplicar ().
• Además, también puede confiar en una serie de servicios angulares incorporados para llamar a $ Digest (). Por ejemplo, el servicio $ HTTP llamará a $ Aplicar () después de que se complete la solicitud XHR y se active el valor de devolución de actualización.
• Siempre que manejemos manualmente los eventos, usemos marcos de terceros (como jQuery, API de Facebook) o llame a SetTimeOut (), podemos usar la función $ Aplicat () para hacer que Angular Devuelva un bucle de $ Digest.
Llamar a setTimeOut ():
<! DocType html> <html ng-app = "myapp"> <head> <title> $ scope. $ Aplic () use </title> <meta charset = "utf-8"> <script src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script> </head> <body> <divi = "div1" ng-concontroller = "mytext"> <div> {{text}}} </div> <input id = "btn" type " valor = "jQuery-event"> </put> </div> </body> </html> <script type = "text/javaScript"> var mymodule = angular.module ('myApp', []); mymodule.controller ("myText", function ($ scope) {$ scope.text = "place"; setTimeOut (function () {$ scope.text = "valor asentado después del tiempo de tiempo"; $ scope. $ apply (); // La detección de valor sucio debe realizarse manualmente, de lo contrario, los datos no se pueden actualizar a la interfaz}, 1000);});}); </script>Use marcos de terceros (como jQuery, API de Facebook):
< src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script> <body> <div ID = "div1" ng-confontroller = "mytext"> <div> {text}}} </div> <input id = "btn" tipo = "botón" valor = "jQuery-event"> </put> </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 = "valor establecido en jQuery"; $ scope. $ apply ();});}) </script>1.3. ¿Cuántas veces se ejecutará el bucle $ Digest?
Cuando se está ejecutando un bucle de $ Digest, los observadores serán ejecutados para verificar si los modelos en el alcance han cambiado. Si se produce un cambio, se ejecutará la función del oyente correspondiente. Esto implica un tema importante. ¿Qué pasa si la función del oyente en sí modificará un modelo de alcance? ¿Cómo manejarán esta situación Angularjs?
La respuesta es que el bucle $ Digest no se ejecutará solo una vez. Después de que termine el bucle actual, ejecutará otro bucle para verificar si los modelos han cambiado. Esta es una verificación sucia, que se usa para manejar los cambios en el modelo que pueden ocurrir cuando se ejecuta la función del oyente. Por lo tanto, el bucle $ Digest continuará ejecutándose hasta que el modelo ya no cambie, o el bucle $ Digest alcanza 10 veces. Por lo tanto, trate de no modificar el modelo en la función del oyente tanto como sea posible.
Nota: El bucle $ Digest también se ejecutará al menos dos veces, incluso si no se cambia ningún modelo en la función del oyente. Como se discutió anteriormente, se ejecutará una vez más para garantizar que los modelos no cambien.
Conclusión
Lo más importante para recordar es si AngularJS puede detectar sus modificaciones al modelo. Si no se puede detectar, entonces debe llamar a $ Aplicar () manualmente.
Si tiene alguna pregunta, déjame un mensaje y el editor responderá a todos a tiempo. ¡Muchas gracias por su apoyo al sitio web de Wulin.com!