入门

监控属性

使用内置绑定

控制文本和外观

绑定逻辑控制

处理表单属性

解析模板

高级应用

插件

更多信息

监控属性

Knockout是在下面三个核心功能是建立起来的:

Knockout is built around three core features:

  • 监控属性(Observables)和依赖跟踪(Dependency tracking)
  • Observables and dependency tracking
  • 声明式绑定(Declarative bindings)
  • Declarative bindings
  • 模板(Templating)
  • Templating

这一节,你讲学到3个功能中的第一个。 在这之前, 我们来解释一下MVVM模式和view model的概念。

On this page, you’ll learn about the first of these three. But before that, let me explain the MVVM pattern and the concept of a view model.

MVVM and View Models

Model-View-View Model (MVVM) 是一种创建用户界面的设计模式。 描述的是如何将复杂的UI用户界面分成3个部分:

Model-View-View Model (MVVM) is a design pattern for building user interfaces. It describes how you can keep a potentially sophisticated UI simple by splitting it into three parts:

  • model:你程序里存储的数据。这个数据包括对象和业务操作(例如:银子账户可以完成转账功能), 并且独立于任何UI。使用KO的时候,通常说是向服务器调用Ajax读写这个存储的模型数据。

A model: your application’s stored data. This data represents objects and operations in your business domain (e.g., bank accounts that can perform money transfers) and is independent of any UI. When using KO, you will usually make Ajax calls to some server-side code to read and write this stored model data.

  • view model: 在UI上,纯code描述的数据以及操作。例如,如果你实现列表编辑,你的view model应该是一个包含列表项items的对象和暴露的add/remove列表项(item)的操作方法。

A view model: a pure-code representation of the data and operations on a UI. For example, if you’re implementing a list editor, your view model would be an object holding a list of items, and exposing methods to add and remove items.

注意这不是UI本身:它不包含任何按钮的概念或者显示风格。它也不是持续数据模型 – 包含用户正在使用的未保存数据。使用KO的时候,你的view models是不包含任何HTML知识的纯JavaScript 对象。保持view model抽象可以保持简单,以便你能管理更复杂的行为。

Note that this is not the UI itself: it doesn’t have any concept of buttons or display styles. It’s not the persisted data model either - it holds the unsaved data the user is working with. When using KO, your view models are pure JavaScript objects that hold no knowledge of HTML. Keeping the view model abstract in this way lets it stay simple, so you can manage more sophisticated behaviors without getting lost.

  • view: 一个可见的,交互式的,表示view model状态的UI。 从view model显示数据,发送命令到view model(例如:当用户click按钮的时候) ,任何view model状态改变的时候更新。

A view: a visible, interactive UI representing the state of the view model. It displays information from the view model, sends commands to the view model (e.g., when the user clicks buttons), and updates whenever the state of the view model changes.

使用KO的时候,你的view就是你带有绑定信息的HTML文档,这些声明式的绑定管理到你的view model上。或者你可以使用模板从你的view model获取数据生成HTML。

When using KO, your view is simply your HTML document with declarative bindings to link it to the view model. Alternatively, you can use templates that generate HTML using data from your view model.

创建一个view model,只需要声明任意的JavaScript object。例如:

  1. var myViewModel = {
  2. personName: 'Bob',
  3. personAge: 123
  4. };

你可以为view model创建一个声明式绑定的简单 view 。例如:下面的代码显示 personName 值:

You can then create a very simple view of this view model using a declarative binding. For example, the following markup displays the personName value:

  1. The name is <span data-bind="text: personName"></span>

激活 Knockout

data-bind 属性尽快好用但它不是HTML的原生属性(它严格遵从HTML5语法, 虽然HTML4验证器提示有不可识别的属性但依然可用)。由于浏览器不识别它是什么意思,所以你需要激活Knockout 来让他起作用。

The data-bind attribute isn’t native to HTML, though it is perfectly OK (it’s strictly compliant in HTML 5, and causes no problems with HTML 4 even though a validator will point out that it’s an unrecognized attribute). But since the browser doesn’t know what it means, you need to activate Knockout to make it take effect.

激活Knockout,需要添加如下的 代码块:

To activate Knockout, add the following line to a block:

  1. ko.applyBindings(myViewModel);

你可以将这个代码块放在HTML底部,或者放在 jQuery’s $ 函数或者ready 函数里

You can either put the script block at the bottom of your HTML document, or you can put it at the top and wrap the contents in a DOM-ready handler such as jQuery’s $ function.

然后放在页面上面, 最终生成结果就是如下的HTML代码::

That does it! Now, your view will display as if you’d written the following HTML:

  1. The name is <span>Bob</span>

你可能奇怪 ko.applyBindings 使用的是什么样的参数,

In case you’re wondering what the parameters to ko.applyBindings do,

  • 第一个参数是你想用于声明式绑定

The first parameter says what view model object you want to use with the declarative bindings it activates

  • 第二个参数(可选),可以声明成使用data-bind的HTML元素或者容器。例如, ko.applyBindings(myViewModel, document.getElementById('someElementId'))。它的现在是只有作为 someElementId 的元素和子元素才能激活KO功能。 好处是你可以在同一个页面声明多个view model,用来区分区域。

Optionally, you can pass a second parameter to define which part of the document you want to search for data-bind attributes. For example, ko.applyBindings(myViewModel, document.getElementById('someElementId')). This restricts the activation to the element with ID someElementId and its descendants, which is useful if you want to have multiple view models and associate each with a different region of the page.

Observables

现在已经知道如何创建一个简单的view model并且通过binding显示它的属性了。但是KO一个重要的功能是当你的view model改变的时候能自动更新你的界面。当你的view model部分改变的时候KO是如何知道的呢?答案是:你需要将你的model属性声明成 observables的, 因为它是非常特殊的JavaScript objects,能够通知订阅者它的改变以及自动探测到相关的依赖。

OK, you’ve seen how to create a basic view model and how to display one of its properties using a binding. But one of the key benefits of KO is that it updates your UI automatically when the view model changes. How can KO know when parts of your view model change? Answer: you need to declare your model properties as observables, because these are special JavaScript objects that can notify subscribers about changes, and can automatically detect dependencies.

例如:将上述例子的view model改成如下代码:

For example, rewrite the preceding view model object as follows:

  1. var myViewModel = {
  2. personName: ko.observable('Bob'),
  3. personAge: ko.observable(123)
  4. };

你根本不需要修改view – 所有的 data-bind 语法依然工作,不同的是他能监控到变化,当值改变时,view会自动更新。

You don’t have to change the view at all - the same data-bind syntax will keep working. The difference is that it’s now capable of detecting changes, and when it does, it will update the view automatically.

监控属性(observables)的读和写

不是所有的浏览器都支持JavaScript的 getters and setters (比如IE),,所以为了兼容性,使用 ko.observable 监控的对象都是真实的 functions函数。

Not all browsers support JavaScript getters and setters ( cough IE cough ), so for compatibility, ko.observable objects are actually functions.

  • 读取监控属性(observable)的值,只需要直接调用监控属性(observable)(不需要参数),例如 myViewModel.personName() 将返回 'Bob',myViewModel.personAge() 将返回 123.

To read the observable’s current value, just call the observable with no parameters. In this example, myViewModel.personName() will return 'Bob', and myViewModel.personAge() will return 123.

  • 写一个新值到监控属性(observable)上,调用这个observable属性并当新值作为参数。例如:调用 myViewModel.personName('Mary') 将更新name值为 'Mary'

To write a new value to the observable, call the observable and pass the new value as a parameter. For example, calling myViewModel.personName('Mary') will change the name value to 'Mary'.

  • 给一个model对象的多个属性写入新值,你可以使用链式语法。例如: myViewModel.personName('Mary').personAge(50) 将会将name更新为 'Mary' 并且将age更新为 50.

To write values to multiple observable properties on a model object, you can use chaining syntax. For example, myViewModel.personName('Mary').personAge(50) will change the name value to 'Mary' and the age value to 50.

监控属性(observables)的特征就是监控(observed),例如其它代码可以说我需要得到对象变化的通知,所以KO内部有很多内置的绑定语法。所以如果你的代码写成 data-bind="text: personName"text 绑定注册到自身,一旦 personName 的值改变,它就能得到通知。

The whole point of observables is that they can be observed, i.e., other code can say that it wants to be notified of changes. That’s what many of KO’s built-in bindings do internally. So, when you wrote data-bind="text: personName", the text binding registered itself to be notified when personName changes (assuming it’s an observable value, which it is now).

当然调用 myViewModel.personName('Mary') 改变name的值, text 绑定将自动更新这个新值到相应的DOM元素上。这就是如何将view model的改变传播到view上的。

When you change the name value to 'Mary' by calling myViewModel.personName('Mary'), the text binding will automatically update the text contents of the associated DOM element. That’s how changes to the view model automatically propagate to the view.

监控属性(Observables)的显式订阅

通常情况下,你不用手工订阅,所以新手可以忽略此小节。

高级用户,如果你要注册自己的订阅到监控属性(observables),你可以调用它的 subscribe 函数。例如:

For advanced users, if you want to register your own subscriptions to be notified of changes to observables, you can call their subscribe function. For example,

  1. myViewModel.personName.subscribe(function(newValue) {
  2. alert("The person's new name is " + newValue);
  3. });

这个 subscribe 函数在内部很多地方都用到的。你也可以终止自己的订阅:首先得到你的订阅,然后调用这个对象的 dispose 函数,例如:

The subscribe function is how many parts of KO work internally. You can also terminate a subscription if you wish: first capture it as a variable, then you can call its dispose function, e.g.:

  1. var subscription = myViewModel.personName.subscribe(function(newValue) { /* do stuff */ });
  2. // ...then later...
  3. subscription.dispose(); // I no longer want notifications

大多数情况下,你不需要做这些,因为内置的绑定和模板系统已经帮你做好很多事情了,可以直接使用它们。

Most of the time you don’t need to do this, because the built-in bindings and templating system take care of managing subscriptions.

(c) knockoutjs.com