提交 4ab766e8 编写于 作者: W wizardforcel

2022-01-08 23:57:39

上级 21b9d8f9
# 介绍
# 零、简介
创建数据驱动的用户界面是 web 开发人员最复杂的工作之一。它需要对接口及其底层数据进行仔细的管理。例如,考虑一个电子商务网站的简单购物车界面。当用户从购物车中删除一个项目时,您必须从基础数据集中删除该项目,从购物车的 HTML 页面中删除关联的元素,并更新总价。除了最琐碎的应用程序之外,找出哪些 HTML 元素依赖于特定的数据是一项容易出错的工作。
......@@ -6,29 +6,29 @@
图 1:手动跟踪 HTML 元素及其底层数据之间的依赖关系
[淘汰赛. js](http://knockoutjs.com/) JavaScript 库提供了一种更干净的方式来管理这些复杂的数据驱动接口。不是手动跟踪 HTML 页面的哪些部分依赖于受影响的数据,而是让您在底层数据及其表示之间创建直接连接。将一个 HTML 元素与一个特定的数据对象链接后,对该对象的任何更改都将自动*反映在 DOM 中。*
[knockout. js](http://knockoutjs.com/) JavaScript 库提供了一种更干净的方式来管理这些复杂的数据驱动接口。不是手动跟踪 HTML 页面的哪些部分依赖于受影响的数据,而是让您在底层数据及其表示之间创建直接连接。将一个 HTML 元素与一个特定的数据对象链接后,对该对象的任何更改都将自动*反映在 DOM 中。*
*![](img/image002.png)
图 2:使用淘汰赛自动跟踪依赖关系
图 2:使用knockout自动跟踪依赖关系
这允许您关注应用程序背后的数据。设置完 HTML 模板后,您可以专门使用 JavaScript 数据对象。使用淘汰赛. js,从购物车中移除一个项目所要做的就是从代表用户购物车项目的 JavaScript 数组中移除它。相应的 HTML 元素将自动从页面中移除,总价将重新计算。
这允许您关注应用程序背后的数据。设置完 HTML 模板后,您可以专门使用 JavaScript 数据对象。使用knockout. js,从购物车中移除一个项目所要做的就是从代表用户购物车项目的 JavaScript 数组中移除它。相应的 HTML 元素将自动从页面中移除,总价将重新计算。
换句话说,淘汰赛. js 允许你为你的 JavaScript 对象设计一个自我更新的显示。
换句话说,knockout. js 允许你为你的 JavaScript 对象设计一个自我更新的显示。
## 其他功能
但是,这并不是淘汰赛所能做到的。除了自动依赖跟踪,它还拥有几个支持快速开发响应用户界面的特性…
但是,这并不是knockout所能做到的。除了自动依赖跟踪,它还拥有几个支持快速开发响应用户界面的特性…
### 纯 JavaScript
淘汰赛. js 是一个完全用 JavaScript 编写的*客户端*库。这使得它几乎可以兼容任何服务器端软件,从 ASP.NET 到 PHP、Django、Ruby on Rails,甚至定制的网络框架。
knockout. js 是一个完全用 JavaScript 编写的*客户端*库。这使得它几乎可以兼容任何服务器端软件,从 ASP.NET 到 PHP、Django、Ruby on Rails,甚至定制的网络框架。
说到前端,淘汰赛. js 通过添加一个单一的 HTML 属性将底层数据模型连接到 HTML 元素。这意味着它可以集成到一个现有的项目中,只需对您的 HTML、CSS 和其他 JavaScript 库进行最小的更改。
说到前端,knockout. js 通过添加一个单一的 HTML 属性将底层数据模型连接到 HTML 元素。这意味着它可以集成到一个现有的项目中,只需对您的 HTML、CSS 和其他 JavaScript 库进行最小的更改。
### 可扩张的
虽然淘汰赛. js 附带了将近 24 个定义数据显示方式的绑定,但您可能仍然需要特定于应用程序的行为(例如,用户提交的电影评论的星级小部件)。幸运的是,淘汰赛. js 使您可以轻松添加自己的绑定,让您完全控制如何将数据转换为 HTML。而且,由于这些自定义绑定被集成到核心模板语言中,所以在应用程序的其他部分重用小部件并不重要。
虽然knockout. js 附带了将近 24 个定义数据显示方式的绑定,但您可能仍然需要特定于应用程序的行为(例如,用户提交的电影评论的星级小部件)。幸运的是,knockout. js 使您可以轻松添加自己的绑定,让您完全控制如何将数据转换为 HTML。而且,由于这些自定义绑定被集成到核心模板语言中,所以在应用程序的其他部分重用小部件并不重要。
![](img/image003.png)
......@@ -36,14 +36,14 @@
### 实用功能
淘汰赛. js 附带了几个实用函数,包括数组过滤器、JSON 解析,甚至还有一种将数据从服务器映射到 HTML 视图的通用方法。这些实用程序使得只需几行代码就可以将大量数据转化为动态用户界面。
knockout. js 附带了几个实用函数,包括数组过滤器、JSON 解析,甚至还有一种将数据从服务器映射到 HTML 视图的通用方法。这些实用程序使得只需几行代码就可以将大量数据转化为动态用户界面。
## 什么是淘汰赛*而不是*
## 什么是knockout*而不是*
淘汰赛. js 是*而不是*是为了替代 jQuery、Prototype 或 MooTools。它并不试图提供动画、通用事件处理或 AJAX 功能(然而,Denking . js 可以*解析*从 AJAX 调用接收的数据)。knowledge . js 只专注于设计可扩展的数据驱动的用户界面,如何获取底层数据完全取决于您。
knockout. js 是*而不是*是为了替代 jQuery、Prototype 或 MooTools。它并不试图提供动画、通用事件处理或 AJAX 功能(然而,Denking . js 可以*解析*从 AJAX 调用接收的数据)。knowledge . js 只专注于设计可扩展的数据驱动的用户界面,如何获取底层数据完全取决于您。
![](img/image004.png)
图 4:淘汰赛. js 补充了一个完整的 web 应用程序堆栈
图 4:knockout. js 补充了一个完整的 web 应用程序堆栈
这种高水平的专门化使得 knowledge . js 与任何其他客户端和服务器端技术兼容,但这也意味着 knowledge . js 通常需要功能更全面的 JavaScript 框架的配合。从这个意义上来说,淘汰赛. js 更多的是对传统 web 应用程序堆栈的*补充*,而不是其不可分割的一部分。*
\ No newline at end of file
这种高水平的专门化使得 knowledge . js 与任何其他客户端和服务器端技术兼容,但这也意味着 knowledge . js 通常需要功能更全面的 JavaScript 框架的配合。从这个意义上来说,knockout. js 更多的是对传统 web 应用程序堆栈的*补充*,而不是其不可分割的一部分。*
\ No newline at end of file
# 第 1 章概念概述
# 一、概念概述
淘汰赛. js 使用模型-视图-视图模型(MVVM)设计模式,这是经典模型-视图-控制器(MVC)模式的变体。与 MVC 模式一样,**模型**是您存储的数据,**视图**是该数据的可视化表示。但是,淘汰赛没有使用控制器,而是使用一个**视图模型**作为模型和视图之间的中介。
knockout. js 使用模型-视图-视图模型(MVVM)设计模式,这是经典模型-视图-控制器(MVC)模式的变体。与 MVC 模式一样,**模型**是您存储的数据,**视图**是该数据的可视化表示。但是,knockout没有使用控制器,而是使用一个**视图模型**作为模型和视图之间的中介。
视图模型是模型数据的 JavaScript 表示,以及用于操作数据的相关函数。knowledge . js 在 ViewModel 和视图之间创建了直接连接,这就是它如何检测底层数据的变化并自动更新用户界面的相关方面。
......@@ -10,28 +10,28 @@
购物车示例的 MVVM 组件如下所示:
* **模型:**存储在数据库、cookie 或其他一些持久存储中的用户购物车的内容。淘汰赛. js 并不关心您的数据是如何存储的,而是由您来决定模型存储和淘汰赛. js 之间的通信。通常,您将通过 AJAX 调用来保存和加载模型数据。
* **模型:**存储在数据库、cookie 或其他一些持久存储中的用户购物车的内容。knockout. js 并不关心您的数据是如何存储的,而是由您来决定模型存储和knockout. js 之间的通信。通常,您将通过 AJAX 调用来保存和加载模型数据。
* **视图:**向用户显示的 HTML/CSS 购物车页面。将视图连接到视图模型后,当视图模型改变时,它将自动显示新的、删除的和更新的项目。
* **ViewModel:** 表示购物车的纯 JavaScript 对象,包括项目列表和用于与模型交互的保存/加载方法。将您的 HTML 视图与视图模型连接后,您的应用程序只需要担心如何操作这个对象。
## 看得见的
淘汰赛. js 使用**可观察到的**来跟踪视图模型的属性。从概念上来说,observables 的行为就像普通的 JavaScript 变量一样,但是它们让 knowledge . js*观察*它们的变化,并自动更新视图的相关部分。
knockout. js 使用**可观测到的**来跟踪视图模型的属性。从概念上来说,observables 的行为就像普通的 JavaScript 变量一样,但是它们让 knowledge . js*观察*它们的变化,并自动更新视图的相关部分。
![](img/image006.png)
图 6:使用可观的东西展示视图模型属性
图 6:使用可观的东西展示视图模型属性
## 粘合剂
仅可观察的*暴露*视图模型的属性。要将视图中的用户界面组件连接到特定的可观察对象,您必须将一个 HTML 元素绑定到它上面**。在将一个元素绑定到一个可观察到的对象之后,淘汰赛. js 就可以自动显示视图模型的变化了。**
仅可观测的*暴露*视图模型的属性。要将视图中的用户界面组件连接到特定的可观测对象,您必须将一个 HTML 元素绑定到它上面**。在将一个元素绑定到一个可观测到的对象之后,knockout. js 就可以自动显示视图模型的变化了。**
![](img/image007.png)
图 7:将用户界面组件绑定到可观的属性
图 7:将用户界面组件绑定到可观的属性
敲除. js 包括几个内置绑定,它们决定了可观的对象在用户界面中的显示方式。最常见的绑定类型是简单地显示观察到的属性的值,但是也可以在特定条件下更改其外观,或者在用户单击元素时调用视图模型的方法。所有这些用例将在接下来的几章中讨论。
敲除. js 包括几个内置绑定,它们决定了可观的对象在用户界面中的显示方式。最常见的绑定类型是简单地显示观察到的属性的值,但是也可以在特定条件下更改其外观,或者在用户单击元素时调用视图模型的方法。所有这些用例将在接下来的几章中讨论。
## 摘要
模型-视图-视图模型设计模式、可观察的对象和绑定为淘汰赛. js 库提供了基础。一旦你理解了这些概念,学习 knowledge . js 就是一件简单的事情,弄清楚如何通过各种内置绑定来访问观察对象和操纵它们。在下一章中,我们将通过构建一个简单的“你好,世界!”应用程序。
\ No newline at end of file
模型-视图-视图模型设计模式、可观测的对象和绑定为knockout. js 库提供了基础。一旦你理解了这些概念,学习 knowledge . js 就是一件简单的事情,弄清楚如何通过各种内置绑定来访问观察对象和操纵它们。在下一章中,我们将通过构建一个简单的“你好,世界!”应用程序。
\ No newline at end of file
# 第二章你好,淘汰赛
# 二、你好,knockout
这一章旨在对淘汰赛. js 的主要组成部分进行高层次的调查。通过实现一个具体的示例应用程序,我们将看到淘汰赛的视图模型、视图、观察点和绑定如何交互来创建一个动态用户界面。
这一章旨在对knockout. js 的主要组成部分进行高层次的调查。通过实现一个具体的示例应用程序,我们将看到knockout的视图模型、视图、观察点和绑定如何交互来创建一个动态用户界面。
首先,我们将创建一个简单的 HTML 页面来保存我们所有的代码,然后我们将定义一个 ViewModel 对象,公开一些属性,甚至添加一个交互式绑定,这样我们就可以对用户的点击做出反应。
## 下载淘汰赛. js
## 下载knockout. js
在我们开始编写任何代码之前,请从 GitHub.com 的[下载页面](https://github.com/SteveSanderson/knockout/downloads)下载最新版本的淘汰赛. js。截至本文撰写之时,最新版本为 2.1.0。之后,我们准备将库添加到一个 HTML 页面。
在我们开始编写任何代码之前,请从 GitHub.com 的[下载页面](https://github.com/SteveSanderson/knockout/downloads)下载最新版本的knockout. js。截至本文撰写之时,最新版本为 2.1.0。之后,我们准备将库添加到一个 HTML 页面。
## 样品
......@@ -14,7 +14,7 @@
## 网页
让我们从一个标准的 HTML 页面开始。在与您的淘汰赛. js 库相同的文件夹中,创建一个名为`index.html`的新文件,并添加以下内容。确保将`knockout-2.1.0.js`更改为您下载的淘汰赛. js 库的文件名。
让我们从一个标准的 HTML 页面开始。在与您的knockout. js 库相同的文件夹中,创建一个名为`index.html`的新文件,并添加以下内容。确保将`knockout-2.1.0.js`更改为您下载的knockout. js 库的文件名。
样本代码:item1.htm
......@@ -41,7 +41,7 @@
图 9:暂时关注视图和视图模型
请记住,视图模型是模型数据的纯 JavaScript 表示。首先,我们将使用一个本地的 JavaScript 对象作为我们的视图模型。在包含淘汰赛. js 的`<script>`标签下,添加以下内容:
请记住,视图模型是模型数据的纯 JavaScript 表示。首先,我们将使用一个本地的 JavaScript 对象作为我们的视图模型。在包含knockout. js 的`<script>`标签下,添加以下内容:
样本代码:item2.htm
......@@ -50,13 +50,13 @@
```
这创建了一个名为约翰·史密斯的“人”,并且`ko.applyBindings()`方法告诉淘汰赛. js 使用该对象作为页面的视图模型。
这创建了一个名为约翰·史密斯的“人”,并且`ko.applyBindings()`方法告诉knockout. js 使用该对象作为页面的视图模型。
当然,如果你重新加载页面,它仍然会显示“比尔的购物车。”为了基于视图模型更新视图,我们需要将一个 HTML 元素绑定到`personViewModel`对象。
## 绑定一个 HTML 元素
淘汰赛. js 使用一个特殊的`data-bind`属性将 HTML 元素绑定到视图模型。用空的`<span>`元素替换`<p>`标签中的`Bill`,如下所示:
knockout. js 使用一个特殊的`data-bind`属性将 HTML 元素绑定到视图模型。用空的`<span>`元素替换`<p>`标签中的`Bill`,如下所示:
样本代码:item2.htm
......@@ -65,7 +65,7 @@
```
`data-bind`属性的值告诉 Lenking . js 在元素中显示什么。在这种情况下,`text`绑定告诉淘汰赛. js 显示视图模型的`firstName`属性。现在,当你重新加载页面时,淘汰赛. js 会用`personViewModel.firstName`替换`<span>`的内容。因此,您应该会在浏览器中看到“约翰的购物车”:
`data-bind`属性的值告诉 Lenking . js 在元素中显示什么。在这种情况下,`text`绑定告诉knockout. js 显示视图模型的`firstName`属性。现在,当你重新加载页面时,knockout. js 会用`personViewModel.firstName`替换`<span>`的内容。因此,您应该会在浏览器中看到“约翰的购物车”:
![](img/image010.png)
......@@ -73,7 +73,7 @@
同样,如果将`data-bind`属性更改为`text: lastName`,将显示“史密斯购物车”如您所见,绑定一个元素实际上只是为您的视图模型定义一个 HTML 模板。
## 可观的属性
## 可观的属性
因此,我们有一个可以在 HTML 元素中显示的视图模型,但是请注意当我们尝试更改属性时会发生什么。调用`ko.applyBindings()`后,给`personViewModel.firstName`赋值:
......@@ -82,7 +82,7 @@
```
淘汰赛. js *不会*自动更新视图,页面依然会显示“约翰的购物车”这是因为我们没有将`firstName`属性暴露给淘汰赛. js,你想要淘汰赛. js 跟踪的任何属性都必须是**可观察的**。我们可以通过将`personViewModel`更改为以下内容来观察视图模型的属性:
knockout. js *不会*自动更新视图,页面依然会显示“约翰的购物车”这是因为我们没有将`firstName`属性暴露给knockout. js,你想要knockout. js 跟踪的任何属性都必须是**可观测的**。我们可以通过将`personViewModel`更改为以下内容来观察视图模型的属性:
样本代码:item3.htm
......@@ -91,7 +91,7 @@
```
我们没有直接给`firstName``lastName`赋值,而是使用`ko.observable()`将属性添加到敲除. js 的自动依赖跟踪器中。当我们更改`firstName`属性时,淘汰赛. js 应该更新 HTML 元素以匹配:
我们没有直接给`firstName``lastName`赋值,而是使用`ko.observable()`将属性添加到敲除. js 的自动依赖跟踪器中。当我们更改`firstName`属性时,knockout. js 应该更新 HTML 元素以匹配:
```js
ko.applyBindings(personViewModel); personViewModel.firstName("Ryan");
......@@ -100,16 +100,16 @@
### 访问观察点
你可能已经注意到,可观测值实际上是函数,而不是变量。要获取一个可观值的值,您可以在没有任何参数的情况下调用它,要设置该值,您可以将该值作为参数传递。这种行为总结如下:
你可能已经注意到,可观测值实际上是函数,而不是变量。要获取一个可观值的值,您可以在没有任何参数的情况下调用它,要设置该值,您可以将该值作为参数传递。这种行为总结如下:
* **获取:**`obj.firstName()`代替`obj.firstName`
* **设置:**`obj.firstName("Mary")`代替`obj.firstName = "Mary"`
适应这些新的访问器对于淘汰赛的初学者来说有点违反直觉。非常小心不要用`=`运算符意外地给可观察的属性赋值。这将覆盖可观察到的内容,导致 Quicken . js 停止自动更新视图。
适应这些新的访问器对于knockout的初学者来说有点违反直觉。非常小心不要用`=`运算符意外地给可观测的属性赋值。这将覆盖可观测到的内容,导致 Quicken . js 停止自动更新视图。
## 使用自定义对象
对于这个简单的例子,我们的通用`personViewModel`对象及其可观的属性工作得很好,但是请记住,视图模型也可以定义与它们的数据交互的方法。因此,视图模型通常被定义为自定义类,而不是通用的 JavaScript 对象。让我们继续,用用户定义的对象替换`personViewModel`:
对于这个简单的例子,我们的通用`personViewModel`对象及其可观的属性工作得很好,但是请记住,视图模型也可以定义与它们的数据交互的方法。因此,视图模型通常被定义为自定义类,而不是通用的 JavaScript 对象。让我们继续,用用户定义的对象替换`personViewModel`:
样本代码:item4.htm
......@@ -129,7 +129,7 @@
## 交互式绑定
本章的最后一步是添加一个结账按钮来调用我们刚刚定义的`checkout()`方法。这是对淘汰赛. js 的交互式绑定的非常简短的介绍,但是它提供了一些有用的功能,我们将在下一章中需要这些功能。在`<p>`标签下方,添加以下按钮:
本章的最后一步是添加一个结账按钮来调用我们刚刚定义的`checkout()`方法。这是对knockout. js 的交互式绑定的非常简短的介绍,但是它提供了一些有用的功能,我们将在下一章中需要这些功能。在`<p>`标签下方,添加以下按钮:
```js
<button data-bind='click: checkout'>Checkout</button>
......@@ -142,16 +142,16 @@
图 11:单击“结帐”按钮后创建的警报消息
淘汰赛. js 的全套交互式绑定将在[第 6 章](06.html#_Chapter_6_Interactive)中介绍。
knockout. js 的全套交互式绑定将在[第 6 章](06.html#_Chapter_6_Interactive)中介绍。
## 摘要
本章详细介绍了淘汰赛. js 的核心方面。正如我们所看到的,设置基于淘汰赛. js 的 web 应用程序有三个步骤:
本章详细介绍了knockout. js 的核心方面。正如我们所看到的,设置基于knockout. js 的 web 应用程序有三个步骤:
1. 创建一个 ViewModel 对象,并将其注册到 Kellow . js。
2. 将 HTML 元素绑定到视图模型的属性之一。
3. 使用可观察的对象将属性公开给淘汰赛
3. 使用可观测的对象将属性公开给knockout
您可以将视图元素绑定到可观察的属性看作是为一个 JavaScript 对象构建一个 HTML 模板。模板设置好之后,您可以完全忘记 HTML,只关注应用程序背后的视图模型数据。这就是淘汰赛的全部意义
您可以将视图元素绑定到可观测的属性看作是为一个 JavaScript 对象构建一个 HTML 模板。模板设置好之后,您可以完全忘记 HTML,只关注应用程序背后的视图模型数据。这就是knockout的全部意义
在下一章中,我们将通过创建依赖于其他属性的可观察值,以及保存数据列表的可观察数组,来探索 well as 自动依赖跟踪器背后的真正力量。
\ No newline at end of file
在下一章中,我们将通过创建依赖于其他属性的可观测值,以及保存数据列表的可观测数组,来探索 well as 自动依赖跟踪器背后的真正力量。
\ No newline at end of file
# 第三章可观察的事物
# 三、可观测对象
我们已经看到了当底层数据发生变化时,可观的属性是如何让敲除器自动更新 HTML 元素的,但这只是它们实用的开始。knowledge . js 还提供了另外两种展示 ViewModel 属性的方式:计算可观测值和可观测数组。总之,这些为数据驱动的用户界面打开了一个全新的可能性世界。
我们已经看到了当底层数据发生变化时,可观的属性是如何让敲除器自动更新 HTML 元素的,但这只是它们实用的开始。knowledge . js 还提供了另外两种展示 ViewModel 属性的方式:计算可观测值和可观测数组。总之,这些为数据驱动的用户界面打开了一个全新的可能性世界。
**计算可观测值**允许您创建动态生成的属性。这意味着您可以将几个正常的可观值组合成一个属性,每当任何基础值发生变化时,敲除. js 仍然会保持视图最新。
**计算可观测值**允许您创建动态生成的属性。这意味着您可以将几个正常的可观值组合成一个属性,每当任何基础值发生变化时,敲除. js 仍然会保持视图最新。
![](img/image012.png)
图 12:依赖于两个正常可观测值的计算可观测值
**可观察数组**结合了 cancel . js 的可观察能力和原生 JavaScript 数组。像本机数组一样,它们包含您可以操作的项目列表。但是由于它们是可观察的,所以每当添加或删除项目时,淘汰赛. js 都会自动更新任何相关的 HTML 元素。
**可观测数组**结合了 cancel . js 的可观测能力和原生 JavaScript 数组。像本机数组一样,它们包含您可以操作的项目列表。但是由于它们是可观测的,所以每当添加或删除项目时,knockout. js 都会自动更新任何相关的 HTML 元素。
![](img/image013.png)
图 13:包含其他视图模型的可观数组
图 13:包含其他视图模型的可观数组
组合观察值的能力,以及处理项目列表的能力,提供了视图模型中所需的所有数据结构。本章通过一个简单的购物车界面介绍了这两个主题。
......@@ -27,29 +27,29 @@
```
这定义了一个匿名函数,每当访问`PersonViewModel.fullName`时,该函数都会返回该人的全名。从现有组件(`firstName``lastName`)动态生成全名可以防止我们存储冗余数据,但这只是成功的一半。我们需要将这个函数传递给`ko.computed()`来创建一个计算的可观测值。这告诉淘汰赛. js,每当`firstName``lastName`发生变化时,它需要更新任何绑定到`fullName`属性的 HTML 元素。
这定义了一个匿名函数,每当访问`PersonViewModel.fullName`时,该函数都会返回该人的全名。从现有组件(`firstName``lastName`)动态生成全名可以防止我们存储冗余数据,但这只是成功的一半。我们需要将这个函数传递给`ko.computed()`来创建一个计算的可观测值。这告诉knockout. js,每当`firstName``lastName`发生变化时,它需要更新任何绑定到`fullName`属性的 HTML 元素。
让我们通过将“约翰的购物车”行绑定到`fullName`而不是`firstName`来确保我们计算的可观值有效:
让我们通过将“约翰的购物车”行绑定到`fullName`而不是`firstName`来确保我们计算的可观值有效:
```js
<p><span data-bind='text: fullName'></span>'s Shopping Cart</p>
```
现在你的页面应该是“约翰·史密斯的购物车”接下来,让我们确保当我们更改一个底层属性时,淘汰赛. js 保持这个 HTML 元素同步。绑定`PersonViewModel`实例后,尝试更改其`firstName`属性:
现在你的页面应该是“约翰·史密斯的购物车”接下来,让我们确保当我们更改一个底层属性时,knockout. js 保持这个 HTML 元素同步。绑定`PersonViewModel`实例后,尝试更改其`firstName`属性:
```js
var vm = new PersonViewModel(); ko.applyBindings(vm); vm.firstName("Mary");
```
这应该会将该行更改为“玛丽·史密斯的购物车”同样,请记住,读取或设置可观值应该通过函数调用来完成,而不是赋值(`=`)运算符。
这应该会将该行更改为“玛丽·史密斯的购物车”同样,请记住,读取或设置可观值应该通过函数调用来完成,而不是赋值(`=`)运算符。
计算出的可观察值提供了许多与敲除. js 的视图自动同步相同的好处。计算的可观察值让您可以围绕原子属性构建应用程序,并将依赖关系跟踪委托给 Lenking . js,而不必跟踪哪些属性依赖于 ViewModel 的其他部分。
计算出的可观测值提供了许多与敲除. js 的视图自动同步相同的好处。计算的可观测值让您可以围绕原子属性构建应用程序,并将依赖关系跟踪委托给 Lenking . js,而不必跟踪哪些属性依赖于 ViewModel 的其他部分。
## 可观阵列
## 可观阵列
可观的数组可以让 Lenking . js 跟踪项目列表。我们将通过为用户创建购物车显示页面来探索这一点。首先,我们需要创建一个自定义对象来表示产品。在我们的脚本顶部,在定义`PersonViewModel`之前,添加以下对象定义:
可观的数组可以让 Lenking . js 跟踪项目列表。我们将通过为用户创建购物车显示页面来探索这一点。首先,我们需要创建一个自定义对象来表示产品。在我们的脚本顶部,在定义`PersonViewModel`之前,添加以下对象定义:
样本代码:item6.htm
......@@ -58,16 +58,16 @@
```
这只是一个存储一些属性的简单数据对象。请注意,可以给多个对象提供可观察的属性,淘汰赛. js 将自行管理所有的相互依赖关系。换句话说,可以在单个应用程序中创建多个视图模型之间的关系。
这只是一个存储一些属性的简单数据对象。请注意,可以给多个对象提供可观测的属性,knockout. js 将自行管理所有的相互依赖关系。换句话说,可以在单个应用程序中创建多个视图模型之间的关系。
接下来,我们将创建几个新的`Product`类的实例,并将它们添加到用户的虚拟购物车中。在`PersonViewModel`内部,定义一个新的可观属性,称为`shoppingCart`:
接下来,我们将创建几个新的`Product`类的实例,并将它们添加到用户的虚拟购物车中。在`PersonViewModel`内部,定义一个新的可观属性,称为`shoppingCart`:
```js
this.shoppingCart = ko.observableArray([ new Product("Beer", 10.99), new Product("Brats", 7.99), new Product("Buns", 1.49) ]);
```
这是一个本机的 JavaScript 数组,包含三个包装在一个可观数组中的产品,这样 Quicken . js 就可以跟踪添加和删除项目的时间。但是,在我们开始操作对象之前,让我们更新我们的视图,以便我们可以看到`shoppingCart`属性的内容。在`<p>`标签下方,添加以下内容:
这是一个本机的 JavaScript 数组,包含三个包装在一个可观数组中的产品,这样 Quicken . js 就可以跟踪添加和删除项目的时间。但是,在我们开始操作对象之前,让我们更新我们的视图,以便我们可以看到`shoppingCart`属性的内容。在`<p>`标签下方,添加以下内容:
样本代码:item6.htm
......@@ -87,17 +87,17 @@
```
这是一个典型的 HTML 5 表格,包含一列产品名称和另一列产品价格。这个例子还引入了一个名为`foreach`的新绑定。当淘汰赛遇到`foreach: shoppingCart`时,它会遍历视图模型的`shoppingCart`属性中的每个项目。循环中的任何标记都是在每个项目的上下文中评估的,所以`text: name`实际上指的是`shoppingCart[i].name`。结果是一张物品及其价格的表格:
这是一个典型的 HTML 5 表格,包含一列产品名称和另一列产品价格。这个例子还引入了一个名为`foreach`的新绑定。当knockout遇到`foreach: shoppingCart`时,它会遍历视图模型的`shoppingCart`属性中的每个项目。循环中的任何标记都是在每个项目的上下文中评估的,所以`text: name`实际上指的是`shoppingCart[i].name`。结果是一张物品及其价格的表格:
![](img/image014.png)
图 14:呈现的产品列表的截图
`foreach`绑定的细节不在本章范围内。下一章提供了对`foreach`的深入讨论,同时也介绍了 knowledge . js 的其他控制流绑定。现在,让我们回到可观的数组。
`foreach`绑定的细节不在本章范围内。下一章提供了对`foreach`的深入讨论,同时也介绍了 knowledge . js 的其他控制流绑定。现在,让我们回到可观的数组。
### 添加项目
使用可观的数组的全部意义在于,每当我们添加或移除项目时,都可以让 Lenking . js 同步视图。例如,我们可以在视图模型上定义一个添加新项目的方法,如下所示:
使用可观的数组的全部意义在于,每当我们添加或移除项目时,都可以让 Lenking . js 同步视图。例如,我们可以在视图模型上定义一个添加新项目的方法,如下所示:
样本代码:item7.htm
......@@ -113,13 +113,13 @@
```
当你点击此按钮时,视图模型的`addProduct()`方法被执行。而且,由于`shoppingCart`是一个可观察的数组,所以淘汰赛. js 会插入另一个`<tr>`元素来显示新项目。与每当我们更改底层数组时试图手动更新`<table>`相比,让淘汰赛. js 跟踪这样的列表项更不容易出错。
当你点击此按钮时,视图模型的`addProduct()`方法被执行。而且,由于`shoppingCart`是一个可观测的数组,所以knockout. js 会插入另一个`<tr>`元素来显示新项目。与每当我们更改底层数组时试图手动更新`<table>`相比,让knockout. js 跟踪这样的列表项更不容易出错。
还值得指出的是,淘汰赛. js 总是使同步用户界面所需的*最小化*变化量。不是每次添加或删除一个项目就重新生成整个列表,淘汰赛. js 跟踪 DOM 的哪些部分受到影响,并且只更新*那些元素。这种内置的优化可以将您的应用程序扩展到数百甚至数千个项目,而不会牺牲响应能力。*
还值得指出的是,knockout. js 总是使同步用户界面所需的*最小化*变化量。不是每次添加或删除一个项目就重新生成整个列表,knockout. js 跟踪 DOM 的哪些部分受到影响,并且只更新*那些元素。这种内置的优化可以将您的应用程序扩展到数百甚至数千个项目,而不会牺牲响应能力。*
### 删除项目
类似地,淘汰赛. js 也可以通过`remove()`方法从可观察的数组中删除项目。在`PersonViewModel`定义中,添加另一种移除项目的方法:
类似地,knockout. js 也可以通过`remove()`方法从可观测的数组中删除项目。在`PersonViewModel`定义中,添加另一种移除项目的方法:
样本代码:item8.htm
......@@ -139,7 +139,7 @@
```
因为我们在`foreach`上下文中,我们必须使用`$root`引用来访问我们的视图模型,而不是循环中的当前项目。如果我们试图在没有这个引用的情况下调用`removeProduct()`,那么淘汰赛. js 就会试图调用`Product`类上的方法,而这个方法是不存在的。下一章将介绍`foreach`的所有可用绑定上下文。
因为我们在`foreach`上下文中,我们必须使用`$root`引用来访问我们的视图模型,而不是循环中的当前项目。如果我们试图在没有这个引用的情况下调用`removeProduct()`,那么knockout. js 就会试图调用`Product`类上的方法,而这个方法是不存在的。下一章将介绍`foreach`的所有可用绑定上下文。
我们在`foreach`循环中的事实也弄乱了`removeProduct()`中的`this`引用,所以点击**移除**按钮实际上会抛出`TypeError`。我们可以使用一个常见的 JavaScript 技巧来解决这类范围问题。在`PersonViewModel`定义的顶部,将`this`分配给一个名为`self`的新变量:
......@@ -155,7 +155,7 @@
```
您现在应该能够使用**添加啤酒****移除**按钮来操作我们的可观察阵列。还要注意的是,淘汰赛. js 会自动将循环中的当前项目作为第一个参数添加到`removeProduct()`中。
您现在应该能够使用**添加啤酒****移除**按钮来操作我们的可观测阵列。还要注意的是,knockout. js 会自动将循环中的当前项目作为第一个参数添加到`removeProduct()`中。
### 销毁物品
......@@ -172,20 +172,20 @@
```
现在当你点击**移除**按钮时,淘汰赛. js *不会*从底层数组中移除该项目。这显示在警告消息中,当您单击“删除”时,该消息应该会减少*而不是*方法`destroy()`不是改变列表,而是给产品添加一个`_destroy`属性,并将其设置为`true`。您可以通过添加另一条警报消息来显示此属性:
现在当你点击**移除**按钮时,knockout. js *不会*从底层数组中移除该项目。这显示在警告消息中,当您单击“删除”时,该消息应该会减少*而不是*方法`destroy()`不是改变列表,而是给产品添加一个`_destroy`属性,并将其设置为`true`。您可以通过添加另一条警报消息来显示此属性:
```js
alert(product._destroy);
```
`_destroy`属性可以对一个可观的列表进行排序,并且只拉出已经被删除的项目。然后,您可以仅将*那些项目发送到服务器端脚本进行删除。当处理 AJAX 请求时,这是一种更有效的管理列表的方法。*
`_destroy`属性可以对一个可观的列表进行排序,并且只拉出已经被删除的项目。然后,您可以仅将*那些项目发送到服务器端脚本进行删除。当处理 AJAX 请求时,这是一种更有效的管理列表的方法。*
*请注意,`foreach`循环知道这个约定,并且仍然从视图中移除相关的`<tr>`元素,即使该项保留在底层数组中。
### 其他数组方法
从内部来说,可观察数组就像普通的可观察属性一样,只是它们由本机 JavaScript 数组而不是字符串、数字或对象支持。与普通的可观察值一样,您可以通过调用不含任何属性的可观察数组来访问基础值:
从内部来说,可观测数组就像普通的可观测属性一样,只是它们由本机 JavaScript 数组而不是字符串、数字或对象支持。与普通的可观测值一样,您可以通过调用不含任何属性的可观测数组来访问基础值:
样本代码:item10.htm
......@@ -196,9 +196,9 @@
调用此方法将循环遍历本机列表的项目,并且它还提供对本机 JavaScript 数组方法的访问,如`push()``pop()``shift()``sort()`等。
然而,淘汰赛. js 在可观察的数组对象上定义了*自己的*版本。例如,在本章前面,我们使用`shoppingCart.push()`来添加一个项目,而不是`shoppingCart().push()`。前者在原生 JavaScript 数组上调用“淘汰赛. js”版本,后者调用`push()`
然而,knockout. js 在可观测的数组对象上定义了*自己的*版本。例如,在本章前面,我们使用`shoppingCart.push()`来添加一个项目,而不是`shoppingCart().push()`。前者在原生 JavaScript 数组上调用“knockout. js”版本,后者调用`push()`
通常使用敲除. js 的数组方法比直接访问底层数组好得多,因为它允许敲除. js 自动更新任何相关的视图组件。淘汰赛. js 提供的可观察数组方法的完整列表如下。其中大多数行为与它们的原生 JavaScript 对应物完全一样。
通常使用敲除. js 的数组方法比直接访问底层数组好得多,因为它允许敲除. js 自动更新任何相关的视图组件。knockout. js 提供的可观测数组方法的完整列表如下。其中大多数行为与它们的原生 JavaScript 对应物完全一样。
* `push()`
* `pop()`
......@@ -215,10 +215,10 @@
## 摘要
在这一章中,我们看到了如何使用计算出的可观测值来将正常的可观测值组合成敲除. js 可以跟踪的复合属性。我们还使用了可观的数组,这是一种使视图模型中的数据列表与 HTML 组件同步的方法。
在这一章中,我们看到了如何使用计算出的可观测值来将正常的可观测值组合成敲除. js 可以跟踪的复合属性。我们还使用了可观的数组,这是一种使视图模型中的数据列表与 HTML 组件同步的方法。
原子的、计算的和数组的可观测值一起提供了典型用户界面所需的所有底层数据类型。计算出的可观测值和可观测数组使得敲除成为快速原型开发的一个很好的选择。它们可以让你把所有复杂的功能放在一个地方,然后让淘汰赛. js 处理剩下的部分。
原子的、计算的和数组的可观测值一起提供了典型用户界面所需的所有底层数据类型。计算出的可观测值和可观测数组使得敲除成为快速原型开发的一个很好的选择。它们可以让你把所有复杂的功能放在一个地方,然后让knockout. js 处理剩下的部分。
例如,创建一个计算出的可观值来计算`shoppingCart`列表中每个项目的总价格并将其显示在页面底部是很简单的。一旦你创建了这个功能,你就可以在任何你需要总价的地方重用它(例如,一个 AJAX 请求),只需要访问一个视图模型属性。
例如,创建一个计算出的可观值来计算`shoppingCart`列表中每个项目的总价格并将其显示在页面底部是很简单的。一旦你创建了这个功能,你就可以在任何你需要总价的地方重用它(例如,一个 AJAX 请求),只需要访问一个视图模型属性。
下一章介绍控制流绑定。我们在本章中使用的`foreach`绑定可能是最常见的控制流工具,但是 cancel . js 还包含了一些用于对我们的 HTML 视图组件进行细粒度控制的绑定。**
\ No newline at end of file
# 第 4 章控制流绑定
# 四、控制流绑定
正如我们在前面几章中看到的,为视图模型设计视图就像为 JavaScript 对象创建一个 HTML 模板。任何模板系统不可或缺的一部分是控制模板执行流程的能力。循环遍历数据列表并根据特定条件包含或排除可视元素的能力使标记最小化成为可能,并使您能够完全控制数据的显示方式。
我们已经看到了`foreach`绑定是如何在一个可观察的数组中循环的,但是淘汰赛. js 还包括两个逻辑绑定:`if``ifnot`。此外,其`with`绑定允许您手动更改模板块的范围。
我们已经看到了`foreach`绑定是如何在一个可观测的数组中循环的,但是knockout. js 还包括两个逻辑绑定:`if``ifnot`。此外,其`with`绑定允许您手动更改模板块的范围。
本章通过扩展上一章中的购物车示例,介绍了 Quicken . js 的控制流绑定。我们还将探究上一章中所掩盖的`foreach`的一些细微差别。
......@@ -23,11 +23,11 @@
```
淘汰赛. js 在`data-bind`属性中遇到`foreach`时,它遍历`shoppingCart`数组,并使用它为包含的标记的**绑定上下文**找到的每个项目。这种绑定上下文就是 Leakout . js 管理循环范围的方式。在这种情况下,这就是为什么我们可以使用`name``price`属性而不用参考`Product`的实例。
knockout. js 在`data-bind`属性中遇到`foreach`时,它遍历`shoppingCart`数组,并使用它为包含的标记的**绑定上下文**找到的每个项目。这种绑定上下文就是 Leakout . js 管理循环范围的方式。在这种情况下,这就是为什么我们可以使用`name``price`属性而不用参考`Product`的实例。
## 使用绑定上下文
使用数组中的每一项作为新的绑定上下文是创建循环的一种方便方式,但是这种行为也使得在迭代中引用当前项之外的对象变得不可能。因此,淘汰赛. js 在每个绑定上下文中都提供了几个特殊的属性。请注意,所有这些属性仅在*视图*中可用,而不是在视图模型中。
使用数组中的每一项作为新的绑定上下文是创建循环的一种方便方式,但是这种行为也使得在迭代中引用当前项之外的对象变得不可能。因此,knockout. js 在每个绑定上下文中都提供了几个特殊的属性。请注意,所有这些属性仅在*视图*中可用,而不是在视图模型中。
### $根属性
......@@ -78,11 +78,11 @@
```
`foreach: tags`循环内部,淘汰赛. js 使用原生字符串“烘焙食品”和“热狗”作为绑定上下文。但是,因为我们想要访问实际的字符串而不是它们的*属性*,所以我们需要`$data`对象。
`foreach: tags`循环内部,knockout. js 使用原生字符串“烘焙食品”和“热狗”作为绑定上下文。但是,因为我们想要访问实际的字符串而不是它们的*属性*,所以我们需要`$data`对象。
### $索引属性
`foreach`循环中,`$index`属性包含数组中当前项目的索引。像淘汰赛中的大多数事情一样,`$index`的值将在您从关联的可观察数组中添加或删除项目时自动更新。如果需要显示每个项目的索引,这是一个有用的属性,如下所示:
`foreach`循环中,`$index`属性包含数组中当前项目的索引。像knockout中的大多数事情一样,`$index`的值将在您从关联的可观测数组中添加或删除项目时自动更新。如果需要显示每个项目的索引,这是一个有用的属性,如下所示:
样本代码:item012.htm
......@@ -107,7 +107,7 @@
```
在可观察的数组、`foreach`绑定和前面讨论的绑定上下文属性之间,您应该拥有在您的淘汰赛. js web 应用程序中利用数组所需的所有工具。
在可观测的数组、`foreach`绑定和前面讨论的绑定上下文属性之间,您应该拥有在您的knockout. js web 应用程序中利用数组所需的所有工具。
## 打折产品
......@@ -120,7 +120,7 @@
```
这给了我们一个条件,我们可以用 Lenking . js 的逻辑绑定来检查。首先,我们将`discount`参数设为可选,给它一个默认值`0`。然后,我们为折扣创建一个可观察到的值,以便 Denking . js 可以跟踪它的变化。最后,我们定义了一个计算的可观察值,它返回了一个用户友好的折扣百分比版本。
这给了我们一个条件,我们可以用 Lenking . js 的逻辑绑定来检查。首先,我们将`discount`参数设为可选,给它一个默认值`0`。然后,我们为折扣创建一个可观测到的值,以便 Denking . js 可以跟踪它的变化。最后,我们定义了一个计算的可观测值,它返回了一个用户友好的折扣百分比版本。
让我们继续为`PersonViewModel.shoppingCart`中的第一个项目增加 20%的折扣:
......@@ -140,13 +140,13 @@
```
只有折扣大于`0`的商品才会出现`<td>`元素中的所有内容。另外,由于`discount`是一个可观察到的,每当条件改变时,淘汰赛. js 会自动重新评估。这只是淘汰赛. js 帮助您专注于驱动应用程序的数据的又一种方式。
只有折扣大于`0`的商品才会出现`<td>`元素中的所有内容。另外,由于`discount`是一个可观测到的,每当条件改变时,knockout. js 会自动重新评估。这只是knockout. js 帮助您专注于驱动应用程序的数据的又一种方式。
![](img/image015.png)
图 15:有条件地为每种产品提供折扣
您可以使用*任何* JavaScript 表达式作为条件:淘汰赛. js 将尝试将字符串作为 JavaScript 代码进行评估,并使用结果来显示或隐藏元素。正如您可能已经猜到的那样,`ifnot`绑定只是否定了表达式。
您可以使用*任何* JavaScript 表达式作为条件:knockout. js 将尝试将字符串作为 JavaScript 代码进行评估,并使用结果来显示或隐藏元素。正如您可能已经猜到的那样,`ifnot`绑定只是否定了表达式。
## 具有绑定的
......@@ -162,7 +162,7 @@
```
`with`块内部,淘汰赛. js 使用`PersonViewModel.featuredProduct`作为绑定上下文。因此,`text: name``text: price`绑定工作正常,没有引用它们的父对象。
`with`块内部,knockout. js 使用`PersonViewModel.featuredProduct`作为绑定上下文。因此,`text: name``text: price`绑定工作正常,没有引用它们的父对象。
当然,为了让前面的 HTML 正常工作,您需要在`PersonViewModel`上定义一个`featuredProduct`属性:
......@@ -175,6 +175,6 @@
本章介绍了`foreach``if``ifnot``with`绑定。这些控制流绑定使您可以完全控制视图模型在视图中的显示方式。
重要的是要认识到淘汰赛. js 的绑定和可观察性之间的关系。从技术上讲,两者是完全独立的。正如我们在这本书的开头所看到的,您可以使用一个带有本地 JavaScript 属性的普通对象(即*而不是*可观察对象)作为您的视图模型,淘汰赛. js 将正确呈现视图的绑定。然而,淘汰赛. js 只会第一次处理模板——没有可观察的,当底层数据改变时,它不能自动更新视图。既然这是淘汰赛. js 的全部内容,您通常会看到绑定引用*可观察的*属性,就像前面例子中的`foreach: shoppingCart`绑定一样。
重要的是要认识到knockout. js 的绑定和可观测性之间的关系。从技术上讲,两者是完全独立的。正如我们在这本书的开头所看到的,您可以使用一个带有本地 JavaScript 属性的普通对象(即*而不是*可观测对象)作为您的视图模型,knockout. js 将正确呈现视图的绑定。然而,knockout. js 只会第一次处理模板——没有可观测的,当底层数据改变时,它不能自动更新视图。既然这是knockout. js 的全部内容,您通常会看到绑定引用*可观测的*属性,就像前面例子中的`foreach: shoppingCart`绑定一样。
既然我们可以控制视图模板背后的逻辑,我们就可以继续控制单个 HTML 元素的外观了。下一章将深入探讨 Denuke . js 有趣的部分:外观绑定。
\ No newline at end of file
# 第 5 章外观绑定
# 五、外观绑定
在上一章中,我们看到了 Quinch . js 的控制流绑定如何为视图代码提供一个基本的模板系统。控制流绑定为应用程序提供了可视化结构,但是一个成熟的模板系统需要的不仅仅是结构。淘汰赛. js 的外观绑定让您可以精确控制单个元素的样式和格式。
在上一章中,我们看到了 Quinch . js 的控制流绑定如何为视图代码提供一个基本的模板系统。控制流绑定为应用程序提供了可视化结构,但是一个成熟的模板系统需要的不仅仅是结构。knockout. js 的外观绑定让您可以精确控制单个元素的样式和格式。
在撰写本文时,淘汰赛. js 附带了六个绑定来控制 HTML 元素的外观:
在撰写本文时,knockout. js 附带了六个绑定来控制 HTML 元素的外观:
* `text: <value>`—设置元素的内容。
* `html: <value>`—设置元素的 HTML 内容。
......@@ -11,7 +11,7 @@
* `style: <object>`—定义元素的`style`属性。
* `attr: <object>`—向元素添加任意属性。
像所有的淘汰赛. js 绑定一样,外观绑定总是出现在 HTML 元素的`data-bind`属性内部。但是与前一章的控制流绑定不同,外观绑定只影响它们相关的元素——它们不改变模板块或绑定上下文。
像所有的knockout. js 绑定一样,外观绑定总是出现在 HTML 元素的`data-bind`属性内部。但是与前一章的控制流绑定不同,外观绑定只影响它们相关的元素——它们不改变模板块或绑定上下文。
## 文本绑定
......@@ -28,7 +28,7 @@
图 16:视图中自动转义的 HTML 实体的`text`绑定
还值得指出的是,淘汰赛. js 在幕后管理跨浏览器问题。对于 IE,它使用`innerText`属性,对于火狐和相关浏览器,它使用`textContent`
还值得指出的是,knockout. js 在幕后管理跨浏览器问题。对于 IE,它使用`innerText`属性,对于火狐和相关浏览器,它使用`textContent`
## html 绑定
......@@ -54,7 +54,7 @@
无论何时渲染动态 HTML——无论是通过`html`绑定还是 ASP。NET—始终确保标记已经过验证。如果需要显示不可信的内容,应该使用`text`绑定,而不是`html`
在前面的片段中,还要注意`featuredProduct`是一个可观察的对象,所以底层对象必须用空的函数调用来引用,而不是直接用`featuredProduct.formattedName`访问属性。同样,这是淘汰赛初学者的常见错误。
在前面的片段中,还要注意`featuredProduct`是一个可观测的对象,所以底层对象必须用空的函数调用来引用,而不是直接用`featuredProduct.formattedName`访问属性。同样,这是knockout初学者的常见错误。
## 可见绑定
......@@ -119,7 +119,7 @@
```
如果产品的折扣大于 15%,淘汰赛. js 将把这个元素呈现如下:
如果产品的折扣大于 15%,knockout. js 将把这个元素呈现如下:
```js
<td style='color: red; font-weight: bold'>
......@@ -137,14 +137,14 @@
```
这将向`<a>`标签添加一个`href`属性,指向存储在`permalink`属性中的任何内容。当然,如果`permalink`是一个可观的,你可以利用 Denuke . js 的自动依赖跟踪的所有好处。由于永久链接通常与数据对象一起存储在永久存储器(例如,博客条目)中,因此以这种方式动态生成链接非常方便。
这将向`<a>`标签添加一个`href`属性,指向存储在`permalink`属性中的任何内容。当然,如果`permalink`是一个可观的,你可以利用 Denuke . js 的自动依赖跟踪的所有好处。由于永久链接通常与数据对象一起存储在永久存储器(例如,博客条目)中,因此以这种方式动态生成链接非常方便。
但是,`attr`绑定不仅仅是创建链接。它允许你在一个 HTML 元素中添加任何属性。这为将您的淘汰赛. js 模板与其他 DOM 库集成打开了各种各样的大门。
但是,`attr`绑定不仅仅是创建链接。它允许你在一个 HTML 元素中添加任何属性。这为将您的knockout. js 模板与其他 DOM 库集成打开了各种各样的大门。
## 摘要
这一章介绍了淘汰赛. js 的外观绑定。当满足特定条件时,这些绑定中的许多会更改 HTML 元素。直接在绑定中定义这些条件是设计模板的一种直观方式,它将视图为中心的代码保持在视图模型之外。
这一章介绍了knockout. js 的外观绑定。当满足特定条件时,这些绑定中的许多会更改 HTML 元素。直接在绑定中定义这些条件是设计模板的一种直观方式,它将视图为中心的代码保持在视图模型之外。
请记住,淘汰赛. js 的目标是通过在数据发生变化时自动同步视图,让您专注于应用程序背后的数据。一旦定义了绑定,就再也不用担心它们了(当然,除非您改变视图模型的结构)。
请记住,knockout. js 的目标是通过在数据发生变化时自动同步视图,让您专注于应用程序背后的数据。一旦定义了绑定,就再也不用担心它们了(当然,除非您改变视图模型的结构)。
本章中展示的外观绑定提供了您需要的所有工具来*显示*您的数据,但是它们不允许我们向视图组件添加任何用户交互。在下一章中,我们将看一下 Dellow . js 是如何管理表单域的。
\ No newline at end of file
# 第六章交互绑定
# 六、交互绑定
表单元素是通过网页与用户交互的常规方式。在 Denuke . js 中使用表单与使用外观绑定非常相似。但是,因为用户可以编辑表单域,所以淘汰赛. js 管理两个方向的更新*。这意味着交互绑定是*双向的*。它们可以通过编程设置,视图将相应更新,**它们可以通过视图设置并通过编程读取。*
表单元素是通过网页与用户交互的常规方式。在 Denuke . js 中使用表单与使用外观绑定非常相似。但是,因为用户可以编辑表单域,所以knockout. js 管理两个方向的更新*。这意味着交互绑定是*双向的*。它们可以通过编程设置,视图将相应更新,**它们可以通过视图设置并通过编程读取。*
*![](img/image019.png)
图 19:淘汰赛. js 在两个方向传播变化
图 19:knockout. js 在两个方向传播变化
例如,您可以从视图模型中设置文本输入字段的值,它将显示在视图中。但是,用户在输入字段中键入一些内容也会导致视图模型上的相关属性更新。关键是,淘汰赛. js 总是确保视图和视图模型是同步的。
例如,您可以从视图模型中设置文本输入字段的值,它将显示在视图中。但是,用户在输入字段中键入一些内容也会导致视图模型上的相关属性更新。关键是,knockout. js 总是确保视图和视图模型是同步的。
淘汰赛. js 包括 11 个用于与用户交互的绑定:
knockout. js 包括 11 个用于与用户交互的绑定:
* `click: <method>`—单击元素时调用 ViewModel 方法。
* `value: <property>`-将表单元素的值链接到视图模型属性。
......@@ -23,7 +23,7 @@
像上一章中介绍的外观绑定一样,这些都是在 HTML 元素的数据绑定属性中定义的。它们中的一些(像`click`绑定)对任何元素都有效,但是其他的(像`checked`)只能用于特定的元素。
使用淘汰赛. js 管理 HTML 表单的一个主要好处是你*仍然*只需要担心数据。每当用户更改表单元素的值时,视图模型将自动反映该更新。这使得将用户输入集成到应用程序的其余部分变得非常容易。
使用knockout. js 管理 HTML 表单的一个主要好处是你*仍然*只需要担心数据。每当用户更改表单元素的值时,视图模型将自动反映该更新。这使得将用户输入集成到应用程序的其余部分变得非常容易。
## 一个超文本标记语言表单
......@@ -79,7 +79,7 @@
![](img/image020.png)
图 20:可观值和表单域之间的双向连接
图 20:可观值和表单域之间的双向连接
我们可以通过包含一个显示用户名的按钮和另一个以编程方式设置用户名的按钮来进一步研究这个问题。这让我们从两端看到`value`绑定是如何工作的:
......@@ -106,7 +106,7 @@
单击**显示名称**将读取视图模型的`firstName`属性,该属性应与`<input>`元素匹配,即使它已经被用户编辑过。**设置名称**按钮设置视图模型的属性值,导致`<input>`元素更新。后者的行为本质上与正常`text`绑定相同。
同样,这种双向同步背后的全部意义是让您专注于数据。设置好`value`绑定后,就可以完全忘记 HTML 表单元素了。只需在 ViewModel 上获取或设置关联的属性,淘汰赛. js 将处理剩下的事情。
同样,这种双向同步背后的全部意义是让您专注于数据。设置好`value`绑定后,就可以完全忘记 HTML 表单元素了。只需在 ViewModel 上获取或设置关联的属性,knockout. js 将处理剩下的事情。
我们不需要`displayName``setName`方法或它们各自的按钮,所以如果你愿意,你可以删除它们。
......@@ -121,7 +121,7 @@
```
当用户触发`mouseover`事件时,淘汰赛. js 调用我们视图模型的`showDetails()`方法。同样,当他或她离开元素时,会调用`hideDetails()`。这两者都采用与`click`绑定的处理程序相同的参数:事件的目标和事件对象本身。现在让我们实现这些方法:
当用户触发`mouseover`事件时,knockout. js 调用我们视图模型的`showDetails()`方法。同样,当他或她离开元素时,会调用`hideDetails()`。这两者都采用与`click`绑定的处理程序相同的参数:事件的目标和事件对象本身。现在让我们实现这些方法:
```js
this.showDetails = function(target, event) { alert("Mouse over"); }; this.hideDetails = function(target, event) { alert("Mouse out"); };
......@@ -164,7 +164,7 @@
### 带有自定义参数的事件处理程序
可以将视图中的自定义参数传递给事件处理程序。这意味着您可以从视图中访问任意信息到视图模型中。在我们的例子中,我们将使用一个自定义参数来标识哪个表单域应该显示它的详细信息。可观到的`details`将包含代表所选元素的字符串,而不是切换。首先,我们将对视图模型进行一些细微的修改:
可以将视图中的自定义参数传递给事件处理程序。这意味着您可以从视图中访问任意信息到视图模型中。在我们的例子中,我们将使用一个自定义参数来标识哪个表单域应该显示它的详细信息。可观到的`details`将包含代表所选元素的字符串,而不是切换。首先,我们将对视图模型进行一些细微的修改:
```js
this.details = ko.observable("");
......@@ -197,7 +197,7 @@
```
事件绑定的设置可能有点复杂,但是一旦你理解了它们是如何工作的,它们就为反应式设计提供了无限的可能性。`event`绑定甚至可以连接到 jQuery 的动画功能,这将在[第 8 章](08.html#_Chapter_8_)中讨论。现在,我们将完成对剩下的淘汰赛. js 交互绑定的探索。幸运的是,它们都没有`event`绑定复杂。
事件绑定的设置可能有点复杂,但是一旦你理解了它们是如何工作的,它们就为反应式设计提供了无限的可能性。`event`绑定甚至可以连接到 jQuery 的动画功能,这将在[第 8 章](08.html#_Chapter_8_)中讨论。现在,我们将完成对剩下的knockout. js 交互绑定的探索。幸运的是,它们都没有`event`绑定复杂。
## 启用/禁用绑定
......@@ -208,7 +208,7 @@
```
可观到的`primaryPhone`可以通过正常的`value`绑定链接到表单域:
可观到的`primaryPhone`可以通过正常的`value`绑定链接到表单域:
```js
<p>
......@@ -241,26 +241,26 @@
```
这将为我们的表单添加一个复选框,并将其链接到视图模型的`annoyMe`属性。一如既往,这是一个双向连接。当用户选择或取消选择该框时,淘汰机. js 会更新视图模型,当您设置视图模型属性的值时,它会更新视图。别忘了定义`annoyMe`的可观性:
这将为我们的表单添加一个复选框,并将其链接到视图模型的`annoyMe`属性。一如既往,这是一个双向连接。当用户选择或取消选择该框时,淘汰机. js 会更新视图模型,当您设置视图模型属性的值时,它会更新视图。别忘了定义`annoyMe`的可观性:
```js
this.annoyMe = ko.observable(true);
```
以这种方式使用`checked`绑定就像在单个复选框和布尔可观值之间创建一对一的关系。
以这种方式使用`checked`绑定就像在单个复选框和布尔可观值之间创建一对一的关系。
![](img/image022.png)
图 22:用一个复选框连接一个布尔可观
图 22:用一个复选框连接一个布尔可观
### 复选框数组
也可以使用`checked`绑定数组。当您将复选框绑定到可观的数组时,选定的框对应于数组中包含的元素,如下图所示:
也可以使用`checked`绑定数组。当您将复选框绑定到可观的数组时,选定的框对应于数组中包含的元素,如下图所示:
![](img/image023.png)
图 23:用多个复选框连接一个可观的数组
图 23:用多个复选框连接一个可观的数组
例如,考虑以下观察到的情况:
......@@ -269,7 +269,7 @@
```
我们可以使用每个`<input>`元素上的`value`属性将这个可观数组中的项目连接到复选框:
我们可以使用每个`<input>`元素上的`value`属性将这个可观数组中的项目连接到复选框:
样本代码:item022.htm
......@@ -298,11 +298,11 @@
图 24:显示`annoyTimes`可观测阵列初始状态的复选框
由于我们使用的是*可观的*数组,连接是双向的——取消选择任何一个框都将从`annoyTimes`数组中移除相应的字符串。
由于我们使用的是*可观的*数组,连接是双向的——取消选择任何一个框都将从`annoyTimes`数组中移除相应的字符串。
### 单选按钮
`checked`绑定的最后一个上下文在单选按钮组中。单选按钮不是布尔或数组,而是将其`value`属性连接到视图模型中的字符串属性。例如,我们可以通过首先将可观到的`annoyTimes`更改为字符串,将复选框数组变成单选按钮组:
`checked`绑定的最后一个上下文在单选按钮组中。单选按钮不是布尔或数组,而是将其`value`属性连接到视图模型中的字符串属性。例如,我们可以通过首先将可观到的`annoyTimes`更改为字符串,将复选框数组变成单选按钮组:
```js
this.annoyTimes = ko.observable('morning');
......@@ -316,11 +316,11 @@
```
每个`<input>`都应该以`"radio"`为其`type`,以`"annoyGroup"`为其`name`。后者与淘汰赛. js 没有任何关系——它只是将它们全部添加到同一个 HTML 单选按钮组中。现在,所选单选按钮的`value`属性将始终存储在`annoyTimes`属性中。
每个`<input>`都应该以`"radio"`为其`type`,以`"annoyGroup"`为其`name`。后者与knockout. js 没有任何关系——它只是将它们全部添加到同一个 HTML 单选按钮组中。现在,所选单选按钮的`value`属性将始终存储在`annoyTimes`属性中。
![](img/image025.png)
图 25:用多个单选按钮连接一个可观的字符串
图 25:用多个单选按钮连接一个可观的字符串
## 选项绑定
......@@ -373,14 +373,14 @@
图 26:试图使用带有`options`绑定的对象
幸运的是,淘汰赛. js 允许您传递一个`optionsText`参数来定义要在`<select>`元素中渲染的对象属性:
幸运的是,knockout. js 允许您传递一个`optionsText`参数来定义要在`<select>`元素中渲染的对象属性:
```js
<select data-bind='options: products, optionsText: "name", value: favoriteProduct'></select>
```
为了让这个片段起作用,您还必须在视图模型上定义一个`favoriteProduct`可观察的对象。淘汰赛. js 将用来自`PersonViewModel.products`*对象*填充这个属性,而不是像上一节那样的字符串。
为了让这个片段起作用,您还必须在视图模型上定义一个`favoriteProduct`可观测的对象。knockout. js 将用来自`PersonViewModel.products`*对象*填充这个属性,而不是像上一节那样的字符串。
## 所选选项绑定
......@@ -400,7 +400,7 @@ HTML 的`<select>`元素的另一种呈现方式是多选列表。配置多选
```
请注意,我们需要为淘汰赛提供相同的对象引用(`brats`)给`products``favoriteProducts`,以正确初始化选择。
请注意,我们需要为knockout提供相同的对象引用(`brats`)给`products``favoriteProducts`,以正确初始化选择。
## hasfocus 绑定
......@@ -413,7 +413,7 @@ HTML 的`<select>`元素的另一种呈现方式是多选列表。配置多选
```
然后,您可以添加一个布尔可观察值来告诉淘汰赛. js 给它焦点:
然后,您可以添加一个布尔可观测值来告诉knockout. js 给它焦点:
样本代码:item026.htm
......
# 第 7 章访问外部数据
# 七、访问外部数据
对于大多数 web 应用程序来说,如果不能将数据传递给服务器,收集用户输入相对来说是没有用的。在本章中,我们将学习如何使用 AJAX 请求从服务器发送和接收信息。这将把*模型*放回模型-视图-视图模型设计模式中
......@@ -6,7 +6,7 @@
图 27:将模型添加回我们的 MVVM 模式
请记住,淘汰赛. js 旨在与任何其他客户端或服务器端技术兼容。这本书使用了 jQuery 的`$.getJSON()``$.post()`函数,但是你可以自由使用任何可以发送和接收 JSON 数据的 JavaScript 框架。同样,服务器端脚本语言完全由您决定。本章没有展示后端代码示例,而是简单地包含了敲除器所期望的 JSON 数据。
请记住,knockout. js 旨在与任何其他客户端或服务器端技术兼容。这本书使用了 jQuery 的`$.getJSON()``$.post()`函数,但是你可以自由使用任何可以发送和接收 JSON 数据的 JavaScript 框架。同样,服务器端脚本语言完全由您决定。本章没有展示后端代码示例,而是简单地包含了敲除器所期望的 JSON 数据。
## 一种新的网页表单
......@@ -75,9 +75,9 @@
## 保存数据
对于普通的 web 应用程序,保存数据是一件简单的事情,将对象转换成 JSON,然后用类似 jQuery 的`$.post()`方法将其发送到服务器。对于淘汰赛. js 应用程序来说,事情有些复杂。不可能使用标准的 JSON 序列化程序将对象转换为字符串,因为视图模型使用可观察的对象,而不是普通的 JavaScript 属性。请记住,可观察对象实际上是函数,因此尝试序列化它们并将结果发送到服务器会有意想不到的结果。
对于普通的 web 应用程序,保存数据是一件简单的事情,将对象转换成 JSON,然后用类似 jQuery 的`$.post()`方法将其发送到服务器。对于knockout. js 应用程序来说,事情有些复杂。不可能使用标准的 JSON 序列化程序将对象转换为字符串,因为视图模型使用可观测的对象,而不是普通的 JavaScript 属性。请记住,可观测对象实际上是函数,因此尝试序列化它们并将结果发送到服务器会有意想不到的结果。
幸运的是,淘汰赛. js 为这个问题提供了一个简单的解决方案:`ko.toJSON()`实用函数。将一个对象传递给`ko.toJSON()`会用其当前值替换该对象的所有可观察属性,并将结果作为 JSON 字符串返回。
幸运的是,knockout. js 为这个问题提供了一个简单的解决方案:`ko.toJSON()`实用函数。将一个对象传递给`ko.toJSON()`会用其当前值替换该对象的所有可观测属性,并将结果作为 JSON 字符串返回。
创建另一个名为“保存数据”的按钮,并将其指向视图模型上的`saveUserData()`方法。然后,可以看到`ko.toJSON()`生成的 JSON,如下所示:
......@@ -97,9 +97,9 @@
## 将数据映射到视图模型
前两节中介绍的加载和保存机制提供了创建丰富用户界面所需的一切,这些用户界面由任意服务器端脚本语言支持。然而,如果您使用的不仅仅是几个属性,手动将加载的数据映射到可观的对象可能会变得非常乏味。
前两节中介绍的加载和保存机制提供了创建丰富用户界面所需的一切,这些用户界面由任意服务器端脚本语言支持。然而,如果您使用的不仅仅是几个属性,手动将加载的数据映射到可观的对象可能会变得非常乏味。
淘汰赛. js 的`mapping`插件通过让您自动将从服务器加载的 JSON 对象映射到 ViewModel observables 来解决这个问题。本质上,`mapping`是我们`saveUserData()``loadUserData()`方法的通用版本。
knockout. js 的`mapping`插件通过让您自动将从服务器加载的 JSON 对象映射到 ViewModel observables 来解决这个问题。本质上,`mapping`是我们`saveUserData()``loadUserData()`方法的通用版本。
`mapping`插件是作为一个单独的项目发布的,所以我们需要[下载](https://github.com/SteveSanderson/knockout.mapping/tree/master/build/output)并在使用前将其包含在我们的 HTML 页面中:
......@@ -115,7 +115,7 @@
```
当我们的应用程序加载时,它会立即对初始用户数据发出 AJAX 请求。您的`/get-intial-data`服务器端脚本应该返回与本章[加载数据](#heading_id_68)部分的示例 JSON 输出相同的内容。一旦数据被加载,我们通过`ko.mapping.fromJS()`创建一个视图模型。这将采用脚本生成的本机 JavaScript 对象,并将每个属性转换为可观的。除了`saveUserData()``loadUserData()`方法,这个动态生成的视图模型具有与`PersonViewModel`完全相同的功能。
当我们的应用程序加载时,它会立即对初始用户数据发出 AJAX 请求。您的`/get-intial-data`服务器端脚本应该返回与本章[加载数据](#heading_id_68)部分的示例 JSON 输出相同的内容。一旦数据被加载,我们通过`ko.mapping.fromJS()`创建一个视图模型。这将采用脚本生成的本机 JavaScript 对象,并将每个属性转换为可观的。除了`saveUserData()``loadUserData()`方法,这个动态生成的视图模型具有与`PersonViewModel`完全相同的功能。
此时,我们只使用来自服务器的数据初始化了我们的视图模型*。`mapping`插件也让我们*以同样的方式更新*一个现有的视图模型。让我们继续向视图模型添加一个显式的`loadUserData()`方法:*
......@@ -124,7 +124,7 @@
```
在旧版本的`loadUserData()`中,我们必须手动将每个数据属性分配给其各自的可观值。但是现在,`mapping`插件为我们做了这一切。请注意,将`data`对象作为第一个参数传递给`ko.mapping.fromJS()`会导致它*更新*视图模型,而不是*初始化*视图模型。
在旧版本的`loadUserData()`中,我们必须手动将每个数据属性分配给其各自的可观值。但是现在,`mapping`插件为我们做了这一切。请注意,将`data`对象作为第一个参数传递给`ko.mapping.fromJS()`会导致它*更新*视图模型,而不是*初始化*视图模型。
`mapping`插件仅与加载数据相关,因此`saveUserData()`不受影响,除了它需要被分配给`viewModel`对象:
......@@ -133,12 +133,12 @@
```
现在我们应该回到本节开始时的位置——加载数据按钮和**保存数据按钮**都应该可以工作,并且淘汰赛. js 应该保持视图和视图模型同步。
现在我们应该回到本节开始时的位置——加载数据按钮和**保存数据按钮**都应该可以工作,并且knockout. js 应该保持视图和视图模型同步。
虽然不是所有敲除. js 项目的必要插件,但`mapping`插件确实可以扩展到复杂的对象,而无需为您添加到视图模型中的每个新属性添加额外的代码行。
## 摘要
在这一章中,我们学习了淘汰赛. js 如何与服务器端脚本进行通信。大多数与 AJAX 相关的功能都来自于 jQuery web 框架,尽管 Quicken . js 确实提供了一个简洁的实用函数,可以将其可观察的内容转换为本机 JavaScript 属性。我们还讨论了`mapping`插件,它提供了一种通用的方法来将一个原生的 JavaScript 对象转换成具有可观察属性的视图模型。
在这一章中,我们学习了knockout. js 如何与服务器端脚本进行通信。大多数与 AJAX 相关的功能都来自于 jQuery web 框架,尽管 Quicken . js 确实提供了一个简洁的实用函数,可以将其可观测的内容转换为本机 JavaScript 属性。我们还讨论了`mapping`插件,它提供了一种通用的方法来将一个原生的 JavaScript 对象转换成具有可观测属性的视图模型。
请记住,淘汰赛. js 是一个纯客户端库。它只用于连接 JavaScript 对象(视图模型)和 HTML 元素。一旦建立了这种关系,您就可以使用您喜欢的任何其他技术与服务器进行通信。在客户端,您可以用 Dojo、Prototype、MooTools 或任何其他支持 AJAX 请求的框架来代替 jQuery。在服务器端,你可以选择 ASP.NET、PHP、Django、Ruby on Rails、Perl、JavaServer Pages……你明白了。这种关注点的分离使得 Quicken . js 成为一个非常灵活的用户界面开发工具。*
\ No newline at end of file
请记住,knockout. js 是一个纯客户端库。它只用于连接 JavaScript 对象(视图模型)和 HTML 元素。一旦建立了这种关系,您就可以使用您喜欢的任何其他技术与服务器进行通信。在客户端,您可以用 Dojo、Prototype、MooTools 或任何其他支持 AJAX 请求的框架来代替 jQuery。在服务器端,你可以选择 ASP.NET、PHP、Django、Ruby on Rails、Perl、JavaServer Pages……你明白了。这种关注点的分离使得 Quicken . js 成为一个非常灵活的用户界面开发工具。*
\ No newline at end of file
# 第八章制作淘汰赛动画
# 八、制作knockout动画
淘汰赛. js 是*不是*一个动画库。每当底层数据发生变化时,所有淘汰赛. js 的自动更新都会立即应用于*。为了动画化它的任何变化,我们需要深入到敲除. js 的内部,并使用另一个像 jQuery 或 MooTools 这样的 JavaScript 框架手动创建动画化的转换。本章坚持使用 jQuery 的动画例程,但是所展示的概念也适用于其他动画库。*
knockout. js 是*不是*一个动画库。每当底层数据发生变化时,所有knockout. js 的自动更新都会立即应用于*。为了动画化它的任何变化,我们需要深入到敲除. js 的内部,并使用另一个像 jQuery 或 MooTools 这样的 JavaScript 框架手动创建动画化的转换。本章坚持使用 jQuery 的动画例程,但是所展示的概念也适用于其他动画库。*
*## 购物车的返回
......@@ -33,7 +33,7 @@
```
希望现在这些都是回顾。我们有一个包含一堆产品的可观数组,一个显示每个产品的`foreach`绑定,以及一个向购物车添加更多商品的按钮。
希望现在这些都是回顾。我们有一个包含一堆产品的可观数组,一个显示每个产品的`foreach`绑定,以及一个向购物车添加更多商品的按钮。
## 列表回调
......@@ -78,14 +78,14 @@ gentle . js 本身是一个强大的用户界面库,但是一旦您将其与 j
```
该复选框充当了`<textarea>`的切换开关,但是由于我们使用的是`visible`绑定,淘汰赛. js 会突然在 DOM 中添加或删除它。为了给`<textarea>`提供一个平稳的过渡,我们将创建一个名为`visibleFade`的自定义绑定:
该复选框充当了`<textarea>`的切换开关,但是由于我们使用的是`visible`绑定,knockout. js 会突然在 DOM 中添加或删除它。为了给`<textarea>`提供一个平稳的过渡,我们将创建一个名为`visibleFade`的自定义绑定:
```js
<textarea data-bind='visibleFade: hasInstructions, value: instructions'>
```
当然,在我们将自定义绑定添加到淘汰赛. js 之前,这是行不通的,我们可以通过将定义绑定的对象添加到`ko.bindingHandlers`来实现,如下面的代码示例所示。这也恰好是定义所有内置绑定的地方。
当然,在我们将自定义绑定添加到knockout. js 之前,这是行不通的,我们可以通过将定义绑定的对象添加到`ko.bindingHandlers`来实现,如下面的代码示例所示。这也恰好是定义所有内置绑定的地方。
```js
ko.bindingHandlers.visibleFade = { init: function(element, valueAccessor) { var value = valueAccessor(); $(element).toggle(value()); }, update: function(element, valueAccessor) { var value = valueAccessor(); value() ? $(element).fadeIn() : $(element).fadeOut(); } }
......@@ -96,10 +96,10 @@ gentle . js 本身是一个强大的用户界面库,但是一旦您将其与 j
`element`参数是被绑定的 DOM 元素,`valueAccessor`是将返回所讨论的视图模型属性的函数。在我们的示例中,`element`引用了`<textarea>`,而`valueAccessor()`返回了对`hasInstructions`的引用。
`update`属性指定了一个函数,每当相关的可观察到的变化时执行,我们的回调使用`hasInstructions`的值将`<textarea>`转换到适当的方向。请记住,您需要调用可观测值来获取其当前值(即`value()`,而不是`value`)。然而,如果`hasInstructions`是一个普通的 JavaScript 属性而不是一个可观察的属性,情况就不是这样了。
`update`属性指定了一个函数,每当相关的可观测到的变化时执行,我们的回调使用`hasInstructions`的值将`<textarea>`转换到适当的方向。请记住,您需要调用可观测值来获取其当前值(即`value()`,而不是`value`)。然而,如果`hasInstructions`是一个普通的 JavaScript 属性而不是一个可观测的属性,情况就不是这样了。
## 摘要
在这一章中,我们发现了两种制作 Quicken . js 视图组件动画的方法。首先,我们向`foreach`绑定添加了回调方法,这让我们可以将项目的添加和移除委托给用户定义的函数。这让我们有机会将 jQuery 的动画转换集成到我们的淘汰赛. js 模板中。然后,我们探索了自定义绑定作为动画任意元素的手段。
在这一章中,我们发现了两种制作 Quicken . js 视图组件动画的方法。首先,我们向`foreach`绑定添加了回调方法,这让我们可以将项目的添加和移除委托给用户定义的函数。这让我们有机会将 jQuery 的动画转换集成到我们的knockout. js 模板中。然后,我们探索了自定义绑定作为动画任意元素的手段。
本章介绍了自定义绑定的一个常见用例,但它们绝不仅限于动画用户界面组件。自定义绑定还可以用来过滤收集的数据,监听自定义事件,或者创建可重用的小部件,如网格和分页内容。如果你能把一个行为封装成一个`init`和一个`update`函数,你就能把它变成一个自定义绑定。*
\ No newline at end of file
# 第九章结论
# 九、总结
gentle . js 是一个纯 JavaScript 库,它使得构建动态的、以数据为中心的用户界面变得非常容易。我们学习了如何使用可观察对象公开视图模型属性,将 HTML 元素绑定到这些可观察对象,使用交互式绑定管理用户输入,将数据导出到服务器端脚本,以及使用自定义绑定制作组件动画。希望您已经准备好将这些知识移植到您的真实网络应用程序中。
gentle . js 是一个纯 JavaScript 库,它使得构建动态的、以数据为中心的用户界面变得非常容易。我们学习了如何使用可观测对象公开视图模型属性,将 HTML 元素绑定到这些可观测对象,使用交互式绑定管理用户输入,将数据导出到服务器端脚本,以及使用自定义绑定制作组件动画。希望您已经准备好将这些知识移植到您的真实网络应用程序中。
这本书涵盖了绝大多数的淘汰赛. js 应用编程接口,但仍有许多细微差别有待发现。这些主题包括:聚合数据类型的自定义绑定,`throttle`扩展程序,用于计算的可观测值的异步评估,以及手动订阅可观测值的事件。然而,所有这些都是高级主题,对于典型的 web 应用程序来说不应该是必需的。尽管如此,淘汰赛. js 提供了大量的可扩展性机会供您探索。
\ No newline at end of file
这本书涵盖了绝大多数的knockout. js 应用编程接口,但仍有许多细微差别有待发现。这些主题包括:聚合数据类型的自定义绑定,`throttle`扩展程序,用于计算的可观测值的异步评估,以及手动订阅可观测值的事件。然而,所有这些都是高级主题,对于典型的 web 应用程序来说不应该是必需的。尽管如此,knockout. js 提供了大量的可扩展性机会供您探索。
\ No newline at end of file
# 附录一
# 十、附录一
正文{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册