Knockoutjs官网翻译系列(三) 使用Computed Observables

书接上回,前面谈到了在视图模型中可以定义普通的observable属性以及observableArray属性实现与UI元素的双向绑定,这一节我们继续探讨第三种可实现绑定的属性类型:computed observables,我称它为计算observable(说实话关于observable怎么翻译我还真拿不准)。

要是你在视图对象中已经定义了一个叫firstName的observable属性和一个叫lastName的observable属性,而你想显示这个人的全名那要如何处理呢?这种情况下就到了computed observables 登场的时候了- 它们是一种依赖于其它observables的方法。并且当依赖的这些observables发生变化的时候会自动进行内容的更新。来个Demo吧:

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

此时你可以添加一个computed observable来显示全名

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

然后像这样绑定UI

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

绑定之后之后无论firstName或者lastName什么时候发生了变化,fullName会自动更新为最新的值。(也就是说当依赖的observable发生变化的时候computed中放置的激活函数每次都会被调用, 并且无论你返回什么都会传递给相应的观察者,比如UI元素或者其它的computed observables)。

依赖链

当然了,因此你也可能创造出一条computed observables链,例如像下面这样的场景:

  • 一个叫items的observable属性,它代表一系列对象
  • 另一个叫selectedIndexes的observable属性,代表了被用户选中的项的下表索引
  • 一个叫selectedItems的computed observable ,它返回一个与selectedIndex相关的对象数组。
  • 另一个computed observable,它返回true或者false,如果selectedItems数组中有值那么返回true,否则返回。某些UI元素例如button,它是否可用取决于这个computed observable的返回值。

修改items 或者 selectedIndexes 会波及并更新到链条中的computed observables,进而会更新绑定到它们的UI元素。

关于‘this’

ko.computed中的第二个参数(上面示例中的this) ,当computed observable函数被调用的时候定义了this到底是什么。如果不传递这个值 ,是不能像代码中那样引用this.firstName或者this.lastName的。有经验的Javascript的程序员应该不会有什么疑惑,因为在computed observable中this指代的就不是AppViewModel对象了,

也就无法访问到里面的属性,所以这里需要重新进行赋值定义。 JavaScript在这一点上看起来很奇怪 。(像C# 和Java 是永远不希望程序员为this进行赋值的, 但是JavaScript需要, 因为它的functions 本身默认是不属于任何对象的。)

  • 这里推荐一个比较流行而且简单的处理方式,避免始终考虑this所处的上下文,如果你的视图模型的构造器拷贝一个this的引用到一个单独的变量中(比较经典的可以起名叫 self),你就可以在其它需要使用之前this的地方使用它,就不用再担心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是在function中被捕获的, 他会在内部functions中始终可用, 例如computed observable的执行函数。

Pure computed observables

如果你的computed observable 只执行简单的计算并返回一个依赖于其它observable的值, 那么最好是这么声明 ko.pureComputed 从而取代一个ko.computed。例如:

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

从这个computed声明为pure起 (如果它的调用方法不直接更改其它对象的状态), Knockout 可以更有效的管理它的再次激活方式以及它的内存使用方式。当没有其它代码再依赖这个属性的时候Knockout 会自动挂起或者释放它。(也就是说会有性能上的优化)

防止computed observables 始终通知订阅者

当一个computed observable 返回一个基本类型值的时候 (number, string, boolean, 或者null), 与它有依赖关系的通常只会在它真正发生改变时接收到通知,如果始终返回同一个值,那么就不会接收到通知。 然而, 可以使用内置的notify extender 保证一个 computed observable’s 的订阅者始终可以在computed observable更新时接收到通知,哪怕更新后的值与之前是相同。使用方式如下:

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

延迟更新通知

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

通常来讲, 一个computed observable 更新后会立即通知它的订阅者。 但是如果一个 computed observable 有很多依赖并更新时会比较耗时, 你可以通过限制更新的间隔时间来获取一个较好的性能。可通过下面的方式来完成:

myViewModel.fullName.extend({ rateLimit: 50 });

判断一个属性是不是一个computed observable

在有些场景下,通过编程来判断一个属性是不是computed observable是非常有用的。 Knockout 提供了一个工具方法, ko.isComputed. 例如在你向后台服务发送数据的时候你可能想把computed observables从提交数据中排除出去。可以这样:

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

此外, Knockout 还提供了一些类似的方法可以操作于observables 和 computed observables:

  • ko.isObservable - 如果是observables或者observableArray或者computed observables那么就返回true。
  • ko.isWritableObservable - 如果是observables或者observableArray或者可写computed observables 那么就返回true。

当computed observable 只在你的UI种使用

如果你只需要在你的UI界面上使用复合全称,你可以像如下这样声明:

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

现在你的UI绑定就变成了一个方法调用,如下:

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

Knockout 会在幕后创建 computed observable来监测绑定表达式依赖了什么observables,并且如果相关元素之后被删除了也会自动释放他(dispose it)。

好了,下节继续!

时间: 2024-12-15 07:13:23

Knockoutjs官网翻译系列(三) 使用Computed Observables的相关文章

Knockoutjs官网翻译系列(二) Observable 数组

承接前文,前文书说道了KO框架中如何使用observable的视图模型属性来与UI元素进行绑定并自动进行双向更新的事儿.observable属性除了服务基础数据类型之外,还定义了专门为服务数组类型的observableArray. 如果你想要监测并响应一个object类型的变化,那么你使用observables.如果你想监测并响应一个集合的变化,就使用observableArray.很多场景下你都会用到它,比如你要在UI上展现或者编辑一个列表内容,期中你会控制他们的展现啊,隐藏啊,添加啊,删除之

Spring官网阅读系列(九):Spring中Bean的生命周期(上)

在之前的文章中,我们一起学习过了官网上容器扩展点相关的知识,包括FactoryBean,BeanFactroyPostProcessor,BeanPostProcessor,其中BeanPostProcessor还剩一个很重要的知识点没有介绍,就是相关的BeanPostProcessor中的方法的执行时机.之所以在之前的文章中没有介绍是因为这块内容涉及到Bean的生命周期.在这篇文章中我们开始学习Bean的生命周期相关的知识,整个Bean的生命周期可以分为以下几个阶段: 实例化(得到一个还没有经

谈谈Python之Django搭建企业级官网(第三篇下部)

转载请注明来源地址和原作者(CFishHome) 前沿 上一篇文章我们学习了URL与视图函数的映射.传递参数的三种方式.转换器的简单使用和include函数分层映射管理.接下来这一篇文章着重介绍Path.re_path.include.reverse.redirect函数的使用和自定义URL转换器.学完这些内容,相信我们对URL和视图都会有了一定的了解和认识.为了让每篇文章具有一定的独立性,我决定每篇文章都重新新建一个项目,便于测试和调试. 预备 首先,我们在Pycharm重新新建一个名为boo

Openstack安装部署指南翻译系列 之 说明(Pike版本官网翻译)

从部署实践来看,部署工作有两大困难,一个是架构设计,一个是排查错误.其中,当部署过程中出现错误,需要排查的时候,如果不了解基础的系统结构原理和基础的安装步骤,是很难定位和解决问题的. 现在Openstack的部署有很多可选项,主要有: 1)根据社区官网最基础的安装文档根据设计对每一个service组件进行安装,这种安装方式最基础,全手工: 2)使用Mirantis公司的Fuel工具进行部署.这种部署方式非常高效,界面友好,Fuel工具真正实现了一键部署,只要设计好网络和功能节点分布,一键部署完成

android測试工具MonkeyRunner--google官网翻译

近期在复习之前的笔记,在回想MonkeyRunner时看了看google官网的内容,写得不错.就翻译出来分享下.事实上google官网真是一个学习的好地方. 基础知识 MonkeyRunner工具提供了一个API用于在Android代码之外控制Android设备和模拟器.通过MonkeyRunner.您能够写出一个Python程序去安装一个Android应用程序或測试包.执行它,向它发送模拟击键.截取它的用户界面图片.并将截图存储于工作站上.monkeyrunner工具的主要设计目的是用于測试功

android测试工具MonkeyRunner--google官网翻译

最近在复习之前的笔记,在回顾MonkeyRunner时看了看google官网的内容,写得不错,就翻译出来分享下.其实google官网真是一个学习的好地方. 基础知识 MonkeyRunner工具提供了一个API用于在Android代码之外控制Android设备和模拟器.通过MonkeyRunner,您可以写出一个Python程序去安装一个Android应用程序或测试包,运行它,向它发送模拟击键,截取它的用户界面图片,并将截图存储于工作站上.monkeyrunner工具的主要设计目的是用于测试功能

RavenDB官网文档翻译系列第一

本系列文章主要翻译自RavenDB官方文档,有些地方做了删减,有些内容整合在一起.欢迎有需要的朋友阅读.毕竟还是中文读起来更亲切吗.下面进入正题. 起航 获取RavenDB RavenDB可以通过NuGet获取,也可以直接在RavenDB官网下载压缩包. 首先了解下压缩包中的内容,可以更好的根据需要进行选择. l  Backup  – 包含用于备份的Raven.Backup工具 l  Bundles – 包含所有非内置的插件,如Authentication和Encryption. l  Clie

【工利其器】工具使用之(四)Android System Trace篇(1)官网翻译

前言 Android 开发者官网中对该工具有专门的介绍,本篇文章作为System Trace系列的开头,笔者先不做任何介绍,仅仅翻译一下官网的介绍.在后续的文章中再整理一份学习教程,以及笔者的实践经历.官网中对System Trace的介绍文档路径为[https://developer.android.google.cn/studio/command-line/systrace?hl=en#java].或者在进入到官网的首页后,按照Android Studio > USER GUIDE > C

卸载 Cloudera Manager 5.1.x.和 相关软件【官网翻译】

问题导读: 1.不同的安装方式,卸载方法存在什么区别?2.不同的操作系统,卸载 Cloudera Manager Server and 数据库有什么区别? 重新安装不完整如果你来到这里,因为你的安装没有完成(例如,如果它是由一个虚拟机超时中断),和你想继续安装,然后重新安装,做到以下几点:删除文件和目录: 个人建议:这一步虽然是官网这么做,但是下面命令还是不要执行,因为我们后面还会用到下面命令 /usr/share/cmf/uninstall-cloudera-manager.sh 复制代码 当