knockout入门(二)
knockout计算属性(Computed Observables)
如果您对firstName有一个可观察的名称,对于lastName有一个可观察的名称,并且想要显示全名怎么办? 那就是计算可观察值的来源-这些函数依赖于一个或多个其他可观察值,并且只要这些依赖关系中的任何一个发生变化,它们都将自动更新。
例如,给定以下视图模型类,
function AppViewModel() {
this.firstName = ko.observable('Bob');
this.lastName = ko.observable('Smith');
}
您可以添加一个可计算的observable以返回全名:
function AppViewModel() {
// ... leave firstName and lastName unchanged ...
this.fullName = ko.computed(function() {
return this.firstName() + " " + this.lastName();
}, this);
}
现在您可以将UI元素绑定到它,例如:
The name is <span data-bind="text: fullName"></span>
并在firstName或lastName发生更改时进行更新(每次其依赖项发生任何更改时,都会调用一次您的评估器函数,并且您返回的任何值都将传递给观察者,例如UI元素或其他计算的可观察对象)。
定义“this”
ko.computed的第二个参数(在上面的示例中,我们传递此参数的位)定义了在评估计算出的可观察值时的this值。 如果不传递它,就不可能引用this.firstName()或this.lastName()。
如果您的AppViewModel函数将对此的引用赋值到另一个变量self时,则可以在整个viewmodel中使用self,不必担心计算属性中this的指向问题。 例如:
function AppViewModel() {
var self = this;
self.firstName = ko.observable('Bob');
self.lastName = ko.observable('Smith');
self.fullName = ko.computed(function() {
return self.firstName() + " " + self.lastName();
});
}
由于self是在函数的闭包中捕获的,因此它在任何嵌套函数(例如计算出的可观察值的求值器)中都保持可用并保持一致。 在事件处理程序中,定义self更加有用,正如您将在许多实时示例中看到的那样。
Pure computed 观察属性
如果您computed只是根据一些ko.observable对象计算并返回一个值,那么最好将其声明为ko.pureComputed而不是ko.computed。 例如:
this.fullName = ko.pureComputed(function() {
return this.firstName() + " " + this.lastName();
}, this);
由于此计算方法会直接修改其他对象或状态,因此Knockout可以更有效地管理其重新评估和内存使用情况。 如果没有其他代码对其有效依赖,则该计算属性将自动挂起或释放它。
计算属性对象始终通知用户
当计算属性对象返回原始值(数字,字符串,布尔值或null)时,通常仅在值实际更改时才通知该对象的依赖项。 但是,可以使用内置的通知扩展程序来确保始终在更新时通知计算出的可观察用户,即使该值相同。 您可以这样应用扩展器:
myViewModel.fullName = ko.pureComputed(function() {
return myViewModel.firstName() + " " + myViewModel.lastName();
}).extend({ notify: 'always' });
延迟和/或禁止更改通知
通常,计算属性会在其依赖关系发生更改时立即更新并立即通知其订阅者。 但是,如果计算属性的值具有许多依赖性或涉及大量的更新,则可以通过限制或延迟计算的可观测值的更新和通知来获得更好的性能。 这是通过使用rateLimit扩展器来实现的,如下所示:
// Ensure updates no more than once per 50-millisecond period
myViewModel.fullName.extend({ rateLimit: 50 });
确定某个属性是否为可计算的可观察值
在某些情况下,需要判断当前对象是否是计算属性,Knockout提供实用程序函数ko.isComputed来帮助解决这种情况。 例如,您可能要从发送回服务器的数据中排除计算出的可观测值。
for (var prop in myObject) {
if (myObject.hasOwnProperty(prop) && !ko.isComputed(myObject[prop])) {
result[prop] = myObject[prop];
}
}
此外,Knockout提供了类似的功能,可对计算属性和计算后的计算属性进行操作:
- ko.isObservable-判断对象是否为observables、observable arrays或computed observables.,返回true。
- ko.isWritableObservable-判断对象是否为observables、observable arrays或 writable computed observables.,返回true。
如果您仅使用 fullname 时,不使用用 firstName、lastName时:
function AppViewModel() {
// ... leave firstName and lastName unchanged ...
this.fullName = function() {
return this.firstName() + " " + this.lastName();
};
}
<html>
The name is <span data-bind="text: fullName()"></span>