Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

unidades:11_rootscope:01_watch [2014/10/23 22:35]
admin [Monitorizando un array]
unidades:11_rootscope:01_watch [2014/10/25 10:26] (actual)
admin [La importancia de $watch]
Línea 36: Línea 36:
   * Línea 11: Ya hemos comprobado que los valores son distintos y ahora que cuando //hacemos// lo que necesitemos hacer. En nuestro ejemplo es simplemente mostrar un ''​alert''​.   * Línea 11: Ya hemos comprobado que los valores son distintos y ahora que cuando //hacemos// lo que necesitemos hacer. En nuestro ejemplo es simplemente mostrar un ''​alert''​.
   * Líneas 14 y 15: Si llamáramos a la función ''​change''​ desde un ''​ng-click''​ o desde donde queramos , como cambia el valor de la propiedad ''​nombre''​ se ejecutará la función de //​callback//​ del ''​$watch''​.   * Líneas 14 y 15: Si llamáramos a la función ''​change''​ desde un ''​ng-click''​ o desde donde queramos , como cambia el valor de la propiedad ''​nombre''​ se ejecutará la función de //​callback//​ del ''​$watch''​.
- 
-Como vemos es muy sencillo el uso de ''​$watch''​. 
  
 <note tip> <note tip>
 Recuerda que es una buena idea comprobar si el valor nuevo es distinto al valor viejo. Recuerda que es una buena idea comprobar si el valor nuevo es distinto al valor viejo.
-  ​if (newValue===oldValue) { +<sxh js> 
-  }+if (newValue===oldValue) { 
 +} 
 +</​sxh>​
 </​note>​ </​note>​
  
 +===== La importancia de $watch =====
 +Como vemos es muy sencillo el uso de ''​$watch''​. Pero , ¿porque es tan importante ''​$watch''?​ Hasta ahora hemos podido hacer cosas similares usando los eventos ''​onClick''​ o ''​onChange''​ ¿Que tiene de diferente? Pues la diferencia es que ya no estamos monitorizando cambios en la vista por ejemplo mediante ''​onChange''​ sino que directamente monitorizamos el propio modelo, eso hace que separemos aun mas la vista del modelo, lo que ayuda a seguir el patrón MVC. 
 +
 +Si lo que realmente queremos es saber cuando ha cambiado el valor de una propiedad de **modelo**, ¿Porque usar el evento ''​onChange''​ para comprobar sise ha modificado? ¿Que ocurre si modificamos la vista? Hay que recordar poner siempre ese ''​onChange''​ y por otro lado y si cambiamos directamente desde JavaScript el valor haciendo una asignación a la propiedad. Con ''​onChange''​ no lo podríamos detectar. Es decir que ''​$watch''​ es mucho mas útil que los eventos del DOM ya que nos permite detectar siempre el cambio independientemente desde donde se haya producido.
 +
 +<note important>​
 +Siempre que puedas utiliza ''​$watch''​ en vez de eventos de los tag HTML como ''​onChange''​ , etc, ya que así estará mas separado el modelo de la vista.
 +</​note>​
 ===== Comparando el objeto ===== ===== Comparando el objeto =====
 ¿Como sabe AngularJS que ha cambiado el valor de una propiedad? La respuesta puede parecer sencilla, con un simple "​!=="​. Eso funciona muy bien con datos escalares como números o texto pero no funciona tan bien con objetos. Si comparamos 2 objetos distintos pero con los mismos valores,​¿deberían ser iguales o distintos? Angular al usar "​!=="​ serian distintos. ¿Como sabe AngularJS que ha cambiado el valor de una propiedad? La respuesta puede parecer sencilla, con un simple "​!=="​. Eso funciona muy bien con datos escalares como números o texto pero no funciona tan bien con objetos. Si comparamos 2 objetos distintos pero con los mismos valores,​¿deberían ser iguales o distintos? Angular al usar "​!=="​ serian distintos.
Línea 152: Línea 160:
 Debido a que la expresión puede ser evaluada muchas veces, dicha expresión debería de costar poco tiempo en ser evaluada. Debido a que la expresión puede ser evaluada muchas veces, dicha expresión debería de costar poco tiempo en ser evaluada.
 </​note>​ </​note>​
-===== Monitorizando un array =====+===== $watchCollection  ​=====
 Otra opción que permite AngularJS en monitorizar si cambia algo de un array. En principio se podría hacer con el tercer parámetro de ''​$watch''​ con el valor de ''​true''​ pero esta opción puede ser demasiado costosa ya que hay que comprobar todas y cada una de las propiedades de cada uno de los objetos del array. Otra opción que permite AngularJS en monitorizar si cambia algo de un array. En principio se podría hacer con el tercer parámetro de ''​$watch''​ con el valor de ''​true''​ pero esta opción puede ser demasiado costosa ya que hay que comprobar todas y cada una de las propiedades de cada uno de los objetos del array.
  
Línea 195: Línea 203:
 }); });
 </​sxh>​ </​sxh>​
 +  * Línea 3: El modelo ahora a monitorizar es un array ''​provincias''​.
 +  * Línea 14: Ahora usamos la función ''​$watchCollection''​. Fijate que ahora la función de //​callback//​ ahora tiene como parámetros los 2 array y no valores escalares.
 +  * Línea 26: Si llamamos al método ''​pop()''​ quitando el último elemento , se ejecutará la función de //​callback//​ de ''​$watchCollection''​
 +  * Línea 30: Si cambiamos el valor de un elemento del array tambien se ejecutará la función de //​callback//​ de ''​$watchCollection''​. Lo que hay que tener en ese caso es que los valores de las propiedades del nuevo objeto son iguales al que ya hay pero en ese caso ''​$watchCollection''​ como es un nuevo objeto si que se detecta el cambio.
  
-===== Monitorizando varias expresiones ​=====+===== $watchGroup ​===== 
 +AngularJS 1.3 dispone de un nuevo método para comprobar mas de un atributo a la vez llamado ''​$watchGroup''​ a éste método se le pasa en vez de una expresión un array de expresiones. La función de //​callback//​ será llamada si al menos una de las expresiones ha cambiado su valor. Este método no es mas que una pequeña ayuda para cuando hay varias propiedades que si cambian queremos tratarlas todas de la misma manera.
  
 +Su funcionamiento es el siguiente:
  
 +<sxh js;​highlight:​ [8,​13,​16,​20]>​
 +app.controller("​PruebaController",​ function($scope) {
 + 
 +  $scope.persona = {
 +    nombre: "​Lorenzo",​
 +    ape1: "​Garcia"​
 +  }
 + 
 +  $scope.$watchGroup(['​persona.nombre','​persona.ape1'​],​ function(newValues,​ oldValues) {
 +    if (newValues === oldValues) {
 +      return;
 +    }
 + 
 +    alert("​Nuevo nombre:"​ + newValues[0] ​ + " y nuevo apellido:"​ + newValues[1]);​
 +  });
 + 
 +  $scope.change1 = function() {
 +    $scope.persona.nombre="​Juan";​
 +  }
 +  ​
 +  $scope.change2 = function() {
 +    $scope.persona.ape1="​Perez";​
 +  }  ​
 +  ​
 +});
 +</​sxh>​
 +  * Línea 8: Usamos el método ''​$watchGroup''​ para monitorizar 2 propiedades:​ ''​persona.nombre''​ y ''​persona.ape1''​.
 +  * Línea 13: Ahora los valores son un array con cada uno de los valores de cada expresión, en el mismo orden en el que se definieron.
 +  * Línea 16 y 20: Tanto si se cambia una propiedad u otra se lanzará la función de //​callback//​ de ''​$watchGroup''​.
  
 +<note important>​
 +Recuerda de ''​$watchGroup''​ solo funcionará con Angular 1.3.0
 +</​note> ​
 +
 +===== Rendimiento =====
 +Ahora una sería de consejos sobre rendimiento de ''​$watch''​ o cualquiera de sus dos variantes.
 +  * Incluir muchos ''​$watch''​tiene un coste de rendimiento de la aplicación. Poner unos cuantos no va a suponer ningún problema pero en caso de tener que monitorizar muchos datos habría que tenerlo en cuenta. ​
 +  * Usar ''​$watchGroup''​ en vez de distintos ''​$watch''​ no supone ninguna mejora en el rendimiento ya que internamente se llamará para cada expresión a ''​$watch''​. ​
 +  * En ''​$watch''​ poner a ''​true''​ el tercer parámetro también supone un coste ya que hay que comparar propiedad por propiedad del objeto.
 +
 +
 +==== Antipatrón ====
 +En algún blog de internet como en [[http://​blog.tomaka17.com/​2012/​12/​random-tricks-when-using-angularjs/​|Random tricks when using AngularJS]] o en [[http://​angularjs4u.com/​tips/​5-quick-angular-js-tips-tricks/​|5 Quick Angular JS Tips and Tricks]] se indica que para mejorar el rendimiento de monitorizar 2 variables, por ejemplo "''​a''"​ y "''​b''":​
 +<sxh js>
 +
 +$scope.$watch("​a",​function(newValue,​oldValue) {
 +});
 +  ​
 +$scope.$watch("​b",​function(newValue,​oldValue) {
 +});
 +</​sxh>​
 +
 +Se puede hacer de la siguiente manera para mejorar el rendimiento al hacer un solo ''​$watch'':​
 +<sxh js>
 +$scope.$watch("​a + b",​function(newValue,​oldValue) {
 +});
 +</​sxh>​
 +
 +De esa forma solo hay un ''​$watch''​ en vez de dos. Esto tiene un problema ya que en aunque solo hay un ''​$watch''​ y mejoramos el rendimiento, ​ hay condiciones que harán que no funcione correctamente. Veamos un ejemplo en el que no funcionaría:​
 +
 +<sxh js;​highlight:​ [6,14]>
 +app.controller("​PruebaController",​ function($scope) {
 + 
 +  $scope.a=5;
 +  $scope.b=1;  ​
 + 
 +  $scope.$watch('​a + b', function(newValue,​ oldValue) {
 +    if (newValue === oldValue) {
 +      return;
 +    }
 + 
 +    alert("​Modificado"​);​
 +  });
 + 
 +  $scope.change = function() {
 +    $scope.a=6;
 +    $scope.b=0;
 +  }
 +
 +});
 +
 +</​sxh>​
 +
 +  * Línea 6: Se monitorizan las propiedades "​a"​ y "​b"​ mediante la expresión ''​a + b''​
 +  * Línea 14: Se modifican las 2 propiedades a la vez.
 +
 +En este caso nunca se llamará a la función de //​callback//​ ya que el antiguo valor de la expresión es 6 al ser la suma de 5 + 1 ((a + b = 5 + 1 = 6)), pero el nuevo valor también es 6 al ser la suma de 6 + 0 ((a + b = 6 + 0 = 6)) , por lo que nunca se detectará el cambio en estos casos. Es decir que la expresión "''​a + b''"​ significa monitorizar la **SUMA** de "''​a''"​ y "''​b''"​ por lo que si dicha suma no cambia nunca se ejecuta la función de //​callback//​.
 ===== Ejemplo ===== ===== Ejemplo =====
 +
 +Ejemplo simple del método ''​$watch''​
  
 {{url>​http://​embed.plnkr.co/​PbLgt2}} {{url>​http://​embed.plnkr.co/​PbLgt2}}
  
 ===== Referencias ===== ===== Referencias =====
- * [[https://​docs.angularjs.org/​api/​ng/​type/​$rootScope.Scope#​$watch|/​ API Reference / ng / type components in ng / $rootScope.Scope / $watch]]+  ​* [[https://​docs.angularjs.org/​api/​ng/​type/​$rootScope.Scope#​$watch|/​ API Reference / ng / type components in ng / $rootScope.Scope / $watch]] 
 +  * [[https://​docs.angularjs.org/​api/​ng/​type/​$rootScope.Scope#​$watchCollection|/​ API Reference / ng / type components in ng / $rootScope.Scope / $watchCollection]] 
 +  * [[https://​docs.angularjs.org/​api/​ng/​type/​$rootScope.Scope#​$watchGroup|/​ API Reference / ng / type components in ng / $rootScope.Scope / $watchGroup]]
unidades/11_rootscope/01_watch.1414096519.txt.gz · Última modificación: 2014/10/23 22:35 por admin
Ir hasta arriba
CC Attribution-Share Alike 3.0 Unported
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0