- 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文件。
输入任意出生日期,观察年龄是如何计算的。