27 November 2015

computeed observable 的作用就是计算一些 observable 变量,然后把返回值作为一个 observable对象,提供给UI使用。这样当 computeed observable 依赖的 observable 变量发生变化的时候,它会自动计算新的值。

有这样一个对象,firstName lastName ,

function AppViewModel() {
    this.firstName = ko.observable('Bob');
    this.lastName = ko.observable('Smith');
}

但是UI需要展示 fullName ,就可以这么做,

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 发生变化,那么 fullName就会重新计算。

管理 this

ko.computed 第二个参数是 this 定义了计算 observable 时的 this 。如果不传递 this 参数 ,knockoutjs 就不能 找到 this.firstName() this.lastName() 。通常传递的this 就是你的 viewmodel 引用 。 如果不传递 this ,ko.computed 中计算时就用它自己作用域的 this 而不是 viewmodel 的了。

为了避免 this 混论,我们有一个公约,就是用 一个变量,比如 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();
    });
}

这样,及时不向ko.computed 传递第二个参数 this ,因为用了 self 缓存了 this ,那么也不会引起 this混乱 。

pure computed observable

如果是简单的计算并返回 observable 对象的值,那么请使用 ko.pureComputed 来代替 ko.computed 。

例如

this.fullName = ko.pureComputed(function() {
    return this.firstName() + " " + this.lastName();
}, this);

因为使用了 pureComputed ,那么knockoutjs 可以更高效的管理内存。(计算时不会去直接修改其他对象或者状态) 如果没有其他代码在内存中以来这个 pureComputed 对象,那么knockoutjs 就是自动释放这部分内存。know more

强制 computed observable 一直发出通知

如果 computed 返回一个原始类型的值(a number, string, boolean, or null),只有当值真正发生变化时才会发出通知。可以用 extend({ notify: ‘always’ }) 来强制通知 。

myViewModel.fullName = ko.pureComputed(function() {
    return myViewModel.firstName() + " " + myViewModel.lastName();
}).extend({ notify: 'always' });

延迟或者抑制通知

// Ensure updates no more than once per 50-millisecond period
myViewModel.fullName.extend({ rateLimit: 50 });

判断某个属性是否在 computed observable 中

有时候,你需要知道你用的对象是否是一个 computed observable 对象,可以使用 ko.isComputed 函数。

for (var prop in myObject) {
    if (myObject.hasOwnProperty(prop) && !ko.isComputed(myObject[prop])) {
        result[prop] = myObject[prop];
    }
}

knockoutjs 还提供其他类似功能的接口函数

  • ko.isObservable 如果是 observable 、 observable 数组 或者 computed observable 就返回 true

  • ko.isWritableObservable 如果是 observable 、 observable 数组 或者 可写的 computed observable 就返回 true (它的另一个别名 ko.isWriteableObservable)

仅仅在 UI 上使用 computed observable

可以像下面这样定义

function AppViewModel() {
    // ... leave firstName and lastName unchanged ...
 
    this.fullName = function() {
        return this.firstName() + " " + this.lastName();
    };
}

那么UI可以这样写

The name is <span data-bind="text: fullName()"></span>

knockoutjs 会自动加上 computed observable ,当相关的UI元素被移除的时候,会释放变量内存。