Учебники

KnockoutJS — вычисляемые наблюдаемые

Вычисляемая наблюдаемая — это функция, которая зависит от одной или нескольких наблюдаемых и автоматически обновляется при изменении базовых наблюдаемых (зависимостей).

Вычисляемые наблюдаемые могут быть связаны.

Синтаксис

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

пример

Давайте посмотрим на следующий пример, который демонстрирует использование вычисляемых наблюдаемых.

Live Demo

<!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>

В следующих строках первые два предназначены для приема входных значений. Третья строка выводит среднее значение этих двух чисел.

<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>

В следующих строках тип Observables a и b является числом, когда они впервые инициализируются внутри ViewModel. Однако в KO каждый вход, принятый из пользовательского интерфейса, по умолчанию имеет формат String. Поэтому их необходимо преобразовать в число, чтобы выполнить над ними арифметическую операцию.

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);

В следующей строке рассчитанное среднее значение отображается в пользовательском интерфейсе. Обратите внимание, что тип привязки данных totalAvg — это просто текст.

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

Выход

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код —

  • Сохраните приведенный выше код в файле computed-observable.htm .

  • Откройте этот файл HTML в браузере.

  • Введите любые 2 числа в текстовые поля и обратите внимание, что среднее значение рассчитывается.

Сохраните приведенный выше код в файле computed-observable.htm .

Откройте этот файл HTML в браузере.

Введите любые 2 числа в текстовые поля и обратите внимание, что среднее значение рассчитывается.

Управление «Это»

Обратите внимание, что в приведенном выше примере второй параметр предоставляется как вычисляемая функция. Невозможно сослаться на Observables a () и b () без предоставления этого .

Чтобы преодолеть это, используется переменная self, которая содержит ссылку на это . При этом нет необходимости отслеживать это по всему коду. Вместо этого можно использовать self .

Следующий код ViewModel переписан для вышеприведенного примера с использованием 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;
   });
}

Чистые вычисляемые наблюдаемые

Вычисляемая наблюдаемая должна быть объявлена ​​как Чистая вычисляемая наблюдаемая, если эта наблюдаемая просто вычисляет и возвращает значение, а не напрямую изменяет другие объекты или состояние. Pure Computed Observables помогает Knockout эффективно управлять переоценкой и использованием памяти.

Уведомление подписчиков явно

Когда Computed Observable возвращает значение примитивного типа данных (String, Boolean, Null и Number), тогда его подписчики уведомляются тогда и только тогда, когда происходит изменение действительного значения. Это означает, что если наблюдаемый объект получил значение, аналогичное предыдущему, его подписчики не уведомляются.

Вы можете сделать Computed Observables всегда явно уведомлять наблюдателей, даже если новое значение совпадает со старым, используя синтаксис notify следующим образом.

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

Ограничение уведомлений об изменениях

Слишком много дорогих обновлений может привести к проблемам с производительностью. Вы можете ограничить количество уведомлений, которые будут получены от Observable, используя атрибут rateLimit следующим образом.

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

Выяснение, если свойство вычисляется наблюдаемым

В определенных ситуациях может потребоваться выяснить, является ли свойство вычисляемой наблюдаемой. Следующие функции могут быть использованы для определения типов наблюдаемых.

Sr.No. функция
1

ko.isComputed

Возвращает true, если свойство является Computed Observable.

2

ko.isObservable

Возвращает true, если для свойства установлено значение Observable, Observable array или Computed Observable.

3

ko.isWritableObservable

Возвращает true, если Observable, Observable массив или Writable Computed Observable. (Это также называется ko.isWriteableObservable)

ko.isComputed

Возвращает true, если свойство является Computed Observable.

ko.isObservable

Возвращает true, если для свойства установлено значение Observable, Observable array или Computed Observable.

ko.isWritableObservable

Возвращает true, если Observable, Observable массив или Writable Computed Observable. (Это также называется ko.isWriteableObservable)

Записываемые вычисляемые наблюдаемые

Вычисляемая наблюдаемая получается из одной или нескольких других наблюдаемых, поэтому доступна только для чтения. Тем не менее, возможно, что можно сделать Computed Observable доступным для записи. Для этого вам нужно предоставить функцию обратного вызова, которая работает с записанными значениями.

Эти записываемые вычисляемые наблюдаемые работают так же, как обычные наблюдаемые. Кроме того, они требуют построения собственной логики для вмешательства в операции чтения и записи.

Можно присвоить значения многим наблюдаемым или вычисляемым наблюдаемым свойствам, используя синтаксис цепочки следующим образом.

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

пример

Следующий пример демонстрирует использование Writable Computable Observable.

Live Demo

<!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>

В приведенном выше коде rawDate является свойством pureComputed, принятым из пользовательского интерфейса. yourAge Observable является производным от rawDate .

Даты в JavaScript обрабатываются в миллисекундах. Следовательно, обе даты (сегодняшняя дата и дата рождения) преобразуются в миллисекунды, а затем разница между ними преобразуется обратно в годы и месяцы.

Выход

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код —

Сохраните приведенный выше код в файле writable_computed_observable.htm .

Откройте этот файл HTML в браузере.

Введите любую дату рождения и обратите внимание, что возраст рассчитывается.