2012-09-17 22 views
76

Una cosa que distingue a AngularJS de otros frameworks JavaScript-MVC es su capacidad para hacer eco de valores encuadernados desde JavaScript a HTML mediante enlaces. Angular lo hace "automáticamente" cuando asigna cualquier valor a la variable $ scope.¿Cómo funciona el enlace y la digestión en AngularJS?

Pero, ¿qué tan automático es esto? Algunas veces, Angular no se dará cuenta del cambio, así que necesito llamar a $ scope. $ Apply() o $ scope. $ Digest() para informarle a angular que recoja el cambio. A veces, cuando ejecuto cualquiera de esos métodos, arroja un error y dice que ya hay un resumen en curso.

Dado que los enlaces (cualquier cosa dentro de {{}} llaves o ng-atributos) se repiten con eval, esto significa que Angular está sondeando constantemente el objeto $ scope para buscar cambios y luego realizar una evaluación para impulsar esos cambios al DOM/HTML? ¿O AngularJS de alguna manera ha descubierto el uso de variables mágicas que desencadenan eventos que se desencadenan cuando un valor variable cambia o se asigna? Nunca he escuchado que sea totalmente compatible con todos los navegadores, así que lo dudo.

¿Cómo AngularJS realiza un seguimiento de sus enlaces y variables de ámbito?

+5

Encontré la sección en http://docs.angularjs.org/guide/concepts#runtime que comienza con "Aquí está la explicación de cómo el ejemplo de Hola mundo logra el efecto de enlace de datos" útil. –

+3

Esta publicación también es útil si aún no la has visto: http://stackoverflow.com/questions/9682092/databinding-in-angularjs/9693933#9693933 – Gloopy

+0

Comenta tu primer párrafo declarativo: la capacidad de Angular para hacer eco valores de JavaScript en HTML utilizando enlaces "suena como una forma confusa de decir" enlace de datos ". Y en este punto en el tiempo realmente no establece Angular aparte de otros marcos como Ember o React. La pregunta es útil, no me malinterprete. Pero ese primer párrafo es solo una opinión con la que estoy en desacuerdo: edité la pregunta pero no me siento lo suficientemente autorizada. –

Respuesta

64

Además del documentation section encontrado por Mark, creo que podemos tratar de enumerar todas las posibles fuentes de cambio.

  1. La interacción del usuario con las entradas HTML ('text', 'number', 'url', 'email', 'radio', 'checkbox'). AngularJS tiene inputDirective. Las entradas 'text', 'number', 'url' y 'email' enlazan listener handler para eventos 'input' o 'keydown'. Operador de escucha calls scope.$apply. 'radio' y 'checkbox' vinculan un manejador similar para el evento click.
  2. Interacción del usuario con el elemento seleccionado. AngularJS tiene selectDirective con un comportamiento similar en el evento 'cambio'.
  3. Cambios periódicos usando $timeout service que también hacen $rootScope.$apply().
  4. eventDirectives (ngClick, etc.) también usan scope.$apply.
  5. $ http también usa $rootScope.$apply().
  6. Los cambios fuera del mundo de AngularJS deben usar scope. $ Aplicar como usted sabe.
+2

+1 para el punto "5. $ http también usa $ rootScope. $ apply(). " Argh. ¿Alguien sabe por qué lo hacen? Esto es muy molesto ... – gecco

5

Como descubrió que no es un sondeo, sino que usa su bucle de ejecución interno, entonces es por eso que necesita usar $ apply() o $ digest() para poner las cosas en movimiento.

Miško's explanation es bastante minucioso, pero lo que falta es que Angular solo intenta hacer que $ scope vuelva a tener un estado interno claro siempre que algo suceda dentro de su propio contexto. Esto puede tomar bastante rebote entre los estados del modelo, así que también es por eso que no puede confiar en $ watch() disparar solo una vez y también por qué debe tener cuidado al configurar manualmente las relaciones entre los modelos o terminará en un sinfín refrescos circulares

+0

Entonces, ¿cómo funciona $ apply (someFn)? ¿Los contenidos de someFn se ejecutarán cuando se ejecute la iteración de aplicación? – matsko

+0

Con $ apply, el código se ejecuta en el alcance angular, que es solo para notificarle que desea que los cambios sean digeridos, consulte: http://docs.angularjs.org/api/ng.$rootScope.Scope#$ aplicar – dain

+0

En caso de que quiera evitar la colisión con $ digest, debe verificar $ phase: https://groups.google.com/d/msg/angular/FJwxJ-XbJaE/1NavZNQBhf4J – dain

Cuestiones relacionadas