- KnockoutJS 教程
- KnockoutJS - 首頁
- KnockoutJS - 概述
- KnockoutJS - 環境設定
- KnockoutJS - 應用
- KnockoutJS - MVVM 框架
- KnockoutJS - 可觀察物件
- 計算型可觀察物件
- KnockoutJS - 宣告式繫結
- KnockoutJS - 依賴項跟蹤
- KnockoutJS - 模板
- KnockoutJS - 元件
- KnockoutJS 資源
- KnockoutJS - 快速指南
- KnockoutJS - 資源
- KnockoutJS - 討論
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>
在下面的程式碼中,可觀察物件a和b在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檔案。
輸入任意出生日期,觀察年齡是如何計算的。