Knockout围绕三个核心功能构建: * 可观测和依赖跟踪 * 声明性绑定 * 模板 在本节中,您将了解这三个选项中的第一个。但在此之前,让我们先来看看MVVM模式和视图模型的概念。 ***** # MVVM 和 View Models 模型-视图-模型(MVVM)是一种用于构建用户界面的设计模式。它描述了如何通过将潜在复杂的UI分为三个部分来保持其简单性: 模型:应用程序存储的数据。此数据表示业务域中的对象和操作(例如,可以执行资金转账的银行帐户),并且独立于任何UI。在使用KO时,您通常会对一些服务器端代码进行Ajax调用,以读取和写入存储的模型数据。 视图模型:UI上数据和操作的纯代码表示。例如,如果您正在实现一个列表编辑器,那么视图模型将是一个包含项目列表的对象,并公开用于添加和删除项目的方法。 请注意,这不是UI本身:它没有任何按钮或显示样式的概念。它也不是持久化数据模型——它保存用户正在处理的未保存数据。使用KO时,视图模型是纯JavaScript对象,不包含HTML知识。以这种方式保持视图模型的抽象可以使其保持简单,因此您可以管理更复杂的行为而不会迷失方向。 视图:表示视图模型状态的可见交互式UI。它显示来自视图模型的信息,向视图模型发送命令(例如,当用户单击按钮时),并在视图模型的状态更改时更新。 使用KO时,视图只是HTML文档,带有声明性绑定,将其链接到视图模型。或者,您可以使用使用视图模型中的数据生成HTML的模板。 要使用KO创建视图模型,只需声明任何JavaScript对象。例如: ``` var myViewModel = { personName: 'Bob', personAge: 123 }; ``` 然后可以使用声明性绑定创建此视图模型的非常简单的视图。例如,以下标记显示personName值: `The name is <span data-bind="text: personName"></span> ` **激活knockout** 数据绑定属性不是HTML的本机属性,尽管它完全正常(它在HTML5中严格兼容,并且不会导致HTML4出现问题,即使验证器会指出它是一个无法识别的属性)。但是由于浏览器不知道它的意思,所以需要激活Knockout使其生效。 要激活敲knockout,请将以下行添加到`<script>`块: ``` ko.applyBindings(myViewModel); ``` 您可以将脚本块放在HTML文档的底部,也可以将其放在顶部,并将内容包装到DOM就绪的处理程序中,例如jQuery的$函数。 就是这样!现在,您的视图将显示为您编写了以下HTML: `The name is Bob` 如果您想知道ko.applyBindings的参数是什么, 第一个参数表示要将哪个视图模型对象与它激活的声明性绑定一起使用 (可选)可以传递第二个参数,以定义要搜索文档的哪部分数据绑定属性。例如,`ko.applyBindings(myViewModel,document.getElementById('someElementId'))`。这将激活限制为ID为someElementId的元素及其子体,如果希望有多个视图模型并将每个视图模型与页面的不同区域关联,这将非常有用。 **Observables** 好的,您已经了解了如何创建基本视图模型以及如何使用绑定显示其属性之一。但是KO的一个关键好处是,当视图模型发生变化时,它会自动更新您的UI。KO如何知道视图模型的某些部分何时更改?答:您需要将您的模型属性声明为可观察的,因为这些是特殊的JavaScript对象,可以通知订阅者更改,并可以自动检测依赖关系。 例如,按如下方式重写前面的视图模型对象: ``` var myViewModel = { personName: ko.observable('Bob'), personAge: ko.observable(123) }; ``` 您根本不必更改视图-相同的数据绑定语法将继续工作。不同之处在于它现在能够检测到变化,一旦检测到变化,它就会自动更新视图。 ***** 读写Observables 并非所有浏览器都支持JavaScript getter和setter(*cough*IE*cough*),因此为了兼容性,ko.observable对象实际上是函数。 要读取可观察对象的当前值,只需调用不带参数的可观察对象。在本例中,`myViewModel.personName()`将返回“Bob”,`myViewModel.personAge()`将返回123。 要向可观察对象写入新值,请调用可观察对象并将新值作为参数传递。例如,调用`myViewModel.personName('Mary')`会将名称值更改为'Mary'。 要将值写入模型对象上的多个可观察属性,可以使用链接语法。例如,`myViewModel.personName('Mary').personAge(50)`将名称值更改为'Mary',年龄值更改为50。 可观察的全部要点是它们可以被观察到,也就是说,其他代码可以说它希望收到更改通知。这就是KO的许多内置绑定在内部所做的。因此,当您编写data bind=“text:personName”时,文本绑定注册自己,以便在personName更改时收到通知(假设它是一个可观察的值,现在是)。 当您通过调用`myViewModel.personName('Mary')`将名称值更改为'Mary'时,文本绑定将自动更新关联DOM元素的文本内容。这就是视图模型的更改自动传播到视图的方式。