KnockoutJS - 計算型可觀察物件



計算型可觀察物件是一個依賴於一個或多個可觀察物件的函式,當其底層可觀察物件(依賴項)發生變化時,它會自動更新。

計算型可觀察物件可以進行鏈式呼叫。

語法

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

示例

讓我們來看下面的示例,它演示了計算型可觀察物件的用法。

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

在下面的程式碼中,可觀察物件ab在ViewModel中第一次初始化時型別為數字。但是,在KO中,從UI接受的每個輸入預設情況下都是字串格式。因此,需要將其轉換為數字才能對其執行算術運算。

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

在下面的程式碼中,計算出的平均值顯示在UI中。請注意,totalAvg 的 data-bind 型別只是文字。

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

輸出

讓我們執行以下步驟來檢視上述程式碼的工作原理:

  • 將上述程式碼儲存到computed-observable.htm檔案中。

  • 在瀏覽器中開啟此HTML檔案。

  • 在文字框中輸入任意兩個數字,觀察平均值是如何計算的。

管理“this”

請注意,在上面的示例中,第二個引數作為this提供給Computed函式。如果沒有提供this,則無法引用可觀察物件a()b()

為了克服這個問題,使用了self變數,它持有this的引用。這樣做,就不需要在整個程式碼中跟蹤this。相反,可以使用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;
   });
}

純計算型可觀察物件

如果可觀察物件只是計算和返回值,而不是直接修改其他物件或狀態,則應將其宣告為計算型可觀察物件。純計算型可觀察物件有助於Knockout更高效地管理重新評估和記憶體使用。

顯式通知訂閱者

當計算型可觀察物件返回原始資料型別值(字串、布林值、空值和數字)時,只有在實際值發生變化時才會通知其訂閱者。這意味著如果可觀察物件接收到的值與前一個值相同,則不會通知其訂閱者。

您可以使用notify語法(如下所示)使計算型可觀察物件始終顯式通知觀察者,即使新值與舊值相同。

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

限制更改通知

過多的昂貴更新會導致效能問題。您可以使用rateLimit屬性(如下所示)限制從可觀察物件接收的通知數量。

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

查詢屬性是否為計算型可觀察物件

在某些情況下,可能需要確定屬性是否為計算型可觀察物件。可以使用以下函式來識別可觀察物件的型別。

序號 函式
1

ko.isComputed

如果屬性是計算型可觀察物件,則返回true

2

ko.isObservable

如果屬性是可觀察物件、可觀察陣列或計算型可觀察物件,則返回true

3

ko.isWritableObservable

如果屬性是可觀察物件、可觀察陣列或可寫計算型可觀察物件,則返回true。(這也稱為ko.isWriteableObservable)

可寫計算型可觀察物件

計算型可觀察物件是從一個或多個其他可觀察物件派生的,因此它是隻讀的。但是,可以使計算型可觀察物件可寫。為此,您需要提供一個對寫入值進行操作的回撥函式。

這些可寫計算型可觀察物件的工作方式與常規可觀察物件一樣。此外,它們需要構建自定義邏輯來干預讀寫操作。

可以使用鏈式語法(如下所示)為許多可觀察物件或計算型可觀察物件屬性賦值。

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

示例

以下示例演示了可寫計算型可觀察物件的用法。

<!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是從UI接受的pureComputed屬性。yourAge可觀察物件是從rawDate派生的。

JavaScript中的日期以毫秒為單位進行處理。因此,兩個日期(今天的日期和出生日期)都轉換為毫秒,然後它們之間的差值再轉換為年和月。

輸出

讓我們執行以下步驟來檢視上述程式碼的工作原理:

  • 將上述程式碼儲存到writable_computed_observable.htm檔案中。

  • 在瀏覽器中開啟此HTML檔案。

  • 輸入任意出生日期,觀察年齡是如何計算的。

廣告
© . All rights reserved.