2. 监控
1.通过监控创建视图模型
1. 监控
Knockout是基于以下三个核心特性:
- 监控和依赖跟踪
- 声明式绑定
- 模板
在本节,你将第一次了解这三个特性,在这之前,我们先来了解以下MVVM模式和视图模型的概念。
2. MVVM和视图模型
Model-View-View Model (MVVM)是一种构建用户界面的设计模式。它描述了如何将存在复杂性的UI简单地分成三个部分:
- 模型:用于你的应用程序存储数据。数据被表现为对象在你的业务逻辑里面进行操作(比如,银行账户可以进行转账业务)而且是和任何UI无关联。当你使用KO,你通常会使用Ajax调用一些服务端的代码来读写用于存储的数据模型。
- 视图模型:在UI上的数据和操作的纯代码表示,比如,如果你想实现一个列表编辑器,你的视图模型会是一个带有一个列表项的对象,而且会暴露出添加项和移除项的方法。
- 视图:一个表示视图模型状态的可视化的、可交互的UI界面。它显示来自视图模型的信息,传递命令给视图模型(比如,当用户点击按钮的时候),同时当视图模型无论何时发生改变的时候自动更新。
使用了KO以后,你的视图即HTML文档通过声明式绑定语法关联到视图模型,因此看起来很简单。另外,你可以通过模板使用来自视图模型的数据生成HTML。
要用KO创建一个视图模型,只要任意定义个一个javascript对象,比如
var myViewModel = {
personName: 'Bob',
personAge: 123
};
然后你可以使用声明式绑定语法创建一个非常简单的视图模型的视图。比如,下面的标记显示personName
的值:
The name is <span data-bind="text: personName"></span>
3. 激活Knockout绑定
data-bind
属性并不是html原生属性,尽管它是完全正确的(它是完全兼容HTML5,在HTML4里面也没有问题,尽管会被语法验证器指出这是未被规范承认的属性)。正因为浏览器不知道它代表什么,你需要激活Knockout来让该属性生效。
要激活Knockout,在<script>
标签块之间添加如下内容:
ko.applyBindings(myViewModel);
你既可以把js代码放在你的html文档的底部,也可以通过DOM-ready处理函数如jQuery的$函数
来包裹内容,然后放在顶部。
就是这样,现在你的视图看起来就像你写了下面的html内容后呈现的一样:
The name is <span>Bob</span>
这个时候如果你肯定很好奇要给 ko.applyBindings
传递什么参数
- 第一个参数表示你要用什么视图模型对象来激活声明式绑定。
- 你可以传递第二个
可选
参数来定义你想绑定文档中哪一部分的data-bind
属性。比如,ko.applyBindings(myViewModel, document.getElementById('someElementId'))
。这个限定了只激活ID为someElementId
元素和子元素,当你想要多个视图模型关联页面中不同区域的时候非常有用。
很简单,真滴。
4. Observable方法
好了,你已经明白怎样创建一个基本的视图模型和怎样使用绑定来显示其中的一个属性。但是KO一个重要的好处是当你的视图模型改变的时候自动更新UI内容。KO怎么知道你的视图模型什么时候改变?答案是你需要通过observable
来定义你的模型属性,因为这些特殊的javascript对象可以通知订阅者发生了什么改变,并能自动检测依赖。
比如,把前面的视图模型改为如下:
var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable(123)
};
你完全不需要改变视图,一样的data-bind
语法会正常工作。不同在于现在有能力检测改变,当发生了改变,会自动改变视图。
5. 读写observable的值
不是所有的浏览器支持javascript的getters和setters(比如,IE)属性,为了兼容性,ko.observable
返回的对象实际上是函数。
- 获取监控对象当前值,只要无参调用observable方法即可。比如,
myViewModel.personName()
会返回'Bob'
, 而myViewModel.personAge()
会返回123
. - 设置监控对象的值,调用observable方法同时把要设置的值作为参数传入。比如,
calling myViewModel.personName('Mary')
会改变name的值为'Mary'
。 - 设置模型对象上的多个监控属性值,你可以使用链式语法。比如,
myViewModel.personName('Mary').personAge(50)
会改变name
值为'Mary'
和age
值为50
.
observables的整个关键点就是他们可以被监控,换句话说,其他的代码想要被告知它发生了变化。这就是许多KO内置绑定实际上做的事情。所以,当我们写data-bind="text: personName"
,text
绑定注册自己可被通知,当personName
改变( 假设它现在是一个监控值)。