KnockoutJS - Observables computados

Computed Observable es una función que depende de uno o más Observables y se actualiza automáticamente cada vez que cambian sus Observables subyacentes (dependencias).

Los Observables computados se pueden encadenar.

Sintaxis

this.varName = ko.computed(function(){
   ...
   ... //  function code
   ...
},this);

Ejemplo

Veamos el siguiente ejemplo que demuestra el uso de Observables Computados.

<!DOCTYPE html>
   <head >
      <title>KnockoutJS Computed Observables</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"></script>
   </head>

   <body>
      <p>Enter first number: <input data-bind = "value: a" /></p>
      <p>Enter second number: <input data-bind = "value: b"/></p>
      <p>Average := <span data-bind="text: totalAvg"></span></p>

      <script>
         function MyViewModel() {
            this.a = ko.observable(10);
            this.b = ko.observable(40);

            this.totalAvg = ko.computed(function() {

               if(typeof(this.a()) !== "number" || typeof(this.b()) !== "number") {
                  this.a(Number(this.a()));   //convert string to Number
                  this.b(Number(this.b()));   //convert string to Number
               }

               total = (this.a() + this.b())/2 ;
               return total;
            },this);
         }

         ko.applyBindings(new MyViewModel());
      </script>

   </body>
</html>

En las siguientes líneas, los dos primeros son para aceptar valores de entrada. La tercera línea imprime el promedio de estos dos números.

<p>Enter first number: <input data-bind = "value: a" /></p>
<p>Enter second number: <input data-bind = "value: b"/></p>
<p>Average := <span data-bind = "text: totalAvg"></span></p>

En las siguientes líneas, tipo de Observables a y bes un número cuando se inicializan por primera vez dentro de ViewModel. Sin embargo, en KO, todas las entradas aceptadas desde la interfaz de usuario están por defecto en el formato String. Por lo tanto, deben convertirse a Número para realizar operaciones aritméticas en ellos.

this.totalAvg = ko.computed(function() {
   
   if(typeof(this.a()) !== "number" || typeof(this.b()) !== "number") {
      this.a(Number(this.a()));   //convert string to Number
      this.b(Number(this.b()));   //convert string to Number
   }
   
   total = (this.a() + this.b())/2 ;
   return total;
},this);

En la siguiente línea, el promedio calculado se muestra en la interfaz de usuario. Tenga en cuenta que el tipo de enlace de datos de totalAvg es solo texto.

<p>Average := <span data-bind = "text: totalAvg"></span></p>

Salida

Realicemos los siguientes pasos para ver cómo funciona el código anterior:

  • Guarde el código anterior en computed-observable.htm archivo.

  • Abra este archivo HTML en un navegador.

  • Ingrese 2 números cualesquiera en los cuadros de texto y observe que se calcula el promedio.

Gestionar 'esto'

Tenga en cuenta que en el ejemplo anterior, el segundo parámetro se proporciona como thisa la función calculada. No es posible referirse a Observablesa() y b() sin proporcionar this.

Para superar esto, self se utiliza una variable que contiene la referencia de this. Al hacerlo, no es necesario realizar un seguimientothisa lo largo del código. En lugar,self puede ser usado.

El siguiente código de ViewModel se reescribe para el ejemplo anterior usando self.

function MyViewModel(){
   self = this;
   self.a = ko.observable(10);
   self.b = ko.observable(40);

   this.totalAvg = ko.computed(function() {
      
      if(typeof(self.a()) !== "number" || typeof(self.b()) !== "number") {
         self.a(Number(self.a()));   //convert string to Number
         self.b(Number(self.b()));   //convert string to Number
      }
      
      total = (self.a() + self.b())/2 ;
      return total;
   });
}

Observables computados puros

Un observable calculado debe declararse como PureCalculado Observable si ese Observable simplemente calcula y devuelve el valor y no modifica directamente los otros objetos o el estado. Pure Computed Observables ayuda a Knockout a administrar la reevaluación y el uso de la memoria de manera eficiente.

Notificar a los suscriptores explícitamente

Cuando un observable calculado devuelve un valor de tipo de datos primitivo (cadena, booleano, nulo y número), se notifica a sus suscriptores si y solo si se produce el cambio de valor real. Significa que si un Observable ha recibido el mismo valor que el valor anterior, sus suscriptores no son notificados.

Puede hacer que Computed Observables siempre notifique explícitamente a los observadores, aunque el nuevo valor sea el mismo que el anterior utilizando el notify sintaxis de la siguiente manera.

myViewModel.property = ko.pureComputed(function() {
   return ...;    // code logic goes here
}).extend({ notify: 'always' });

Limitación de notificaciones de cambios

Demasiadas actualizaciones costosas pueden provocar problemas de rendimiento. Puede limitar la cantidad de notificaciones que se recibirán de Observable usandorateLimit atributo de la siguiente manera.

// make sure there are updates no more than once per 100-millisecond period
myViewModel.property.extend({ rateLimit: 100 });

Averiguar si una propiedad se calcula como observable

En determinadas situaciones, puede ser necesario averiguar si una propiedad es un observable calculado. Las siguientes funciones se pueden utilizar para identificar los tipos de Observables.

No Señor. Función
1

ko.isComputed

Devoluciones true si la propiedad es observable calculada.

2

ko.isObservable

Devoluciones true si la propiedad es Observable, Observable array o Computed Observable.

3

ko.isWritableObservable

Devoluciones truesi es observable, matriz observable o escribible calculado observable. (Esto también se llama ko.isWriteableObservable)

Observables computarizados escribibles

Computed Observable se deriva de uno o varios otros Observables, por lo que es de solo lectura. Sin embargo, es posible que uno pueda hacer que se pueda escribir en Computed Observable. Para ello, debe proporcionar una función de devolución de llamada que funcione con valores escritos.

Estos Observables computarizados escribibles funcionan igual que los Observables normales. Además, requieren la creación de una lógica personalizada para interferir en las acciones de lectura y escritura.

Se pueden asignar valores a muchas propiedades observables o observables calculadas utilizando la sintaxis de encadenamiento de la siguiente manera.

myViewModel.fullName('Tom Smith').age(45)

Ejemplo

El siguiente ejemplo demuestra el uso de Writable Computable Observable.

<!DOCTYPE html>
   <head >
      <title>KnockoutJS Writable Computed Observable</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"></script>
   </head>

   <body>
      <p>Enter your birth Date: <input type = "date" data-bind = "value: rawDate" ></p>
      <p><span data-bind = "text: yourAge"></span></p>

      <script>
         function MyViewModel() {
            this.yourAge = ko.observable();
            today = new Date();
            rawDate = ko.observable();

            this.rawDate = ko.pureComputed ({

               read: function() {
                  return this.yourAge;
               },

               write: function(value) {
                  var b = Date.parse(value);    // convert birth date into milliseconds
                  var t = Date.parse(today);    // convert todays date into milliseconds
                  diff = t - b;                 // take difference
                  var y = Math.floor(diff/31449600000);     // difference is converted
                                                            // into years. 31449600000
                                                            //milliseconds form a year.

                  var m = Math.floor((diff % 31449600000)/604800000/4.3);  // calculating
                                                                           // months.
                                                                           // 604800000
                                                                           // milliseconds
                                                                           // form a week.

                  this.yourAge("You are " + y + " year(s) " + m +" months old.");
               },
               owner: this
            });
         }

         ko.applyBindings(new MyViewModel());
      </script>

   </body>
</html>

En el código anterior, rawDate es propiedad pureComputed aceptada de UI. yourAge Observable se deriva de rawDate.

Las fechas en JavaScript se manipulan en milisegundos. Por lo tanto, ambas fechas (la fecha actual y la fecha de nacimiento) se convierten en milisegundos y luego la diferencia entre ellas se vuelve a convertir en años y meses.

Salida

Realicemos los siguientes pasos para ver cómo funciona el código anterior:

  • Guarde el código anterior en writable_computed_observable.htm archivo.

  • Abra este archivo HTML en un navegador.

  • Ingrese cualquier fecha de nacimiento y observe que se calcula la edad.