Knockout Code with KnockoutJS






4.50/5 (2投票s)
快速上手数据绑定和 KnockoutJS。
如果您最近在进行任何客户端 JavaScript 编码,尤其是单页应用程序,那么不利用至少一种可用的 JavaScript 库或框架将会是疯狂的。这些库的主要好处之一就是数据绑定,特别是双向数据绑定。实现双向声明性数据绑定可以显著减少您的代码量,并使您的 Web 应用程序更易于阅读和理解。
实现双向数据绑定的两个最知名的库是 AngularJS 和 KnockoutJS。虽然 AngularJS 越来越受欢迎,并且提供了比 KnockoutJS 多得多的功能,但它无疑更复杂,更难上手,并且在某种程度上将您(开发者)束缚在它自己的框架或架构中。另一方面,KnockoutJS 主要只做一件事:数据绑定,而且做得很好。然而,正如您将看到的,这一件事可以极大地影响您的 Web 应用程序的可读性和可维护性。
HTML 和 JavaScript 的数据绑定在本质上是一个非常简单的概念。它提供了一种将 DOM 元素(HTML)与 JavaScript 对象或变量关联起来的方法,并使它们保持同步,以便当其中一个发生变化时,相关的实体也会自动发生变化。例如,当用户编辑与 JavaScript 变量(或数据位置)绑定的 <input>
HTML 元素的值时,变量也会被更新。您无需编写代码,例如在页面提交时,查找正确的 DOM 元素并将相应的值复制到 JavaScript 变量或对象中。
现在您已经对数据绑定有了基本了解,让我们更实际一些,编写一些代码来利用 KnockoutJS 的优势。我们将从一个实际上只代表单向数据绑定的简单示例开始。
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript" src="jquery-1_11_2_min.js"></script>
<script type="text/javascript" src="knockout-3.3.0.js" ></script>
<script>
var theViewModel = null;
$(document).ready(function ()
{
theViewModel = ViewModel();
ko.applyBindings(theViewModel);
});
function ViewModel()
{
var self = this;
self.FirstName = "Tom";
self.LastName = "Brady";
return self;
}
function firstName_OnBlur()
{
alert(theViewModel.FirstName);
}
</script>
</head>
<body>
<div>
<label>First Name:</label>
<input type="text" data-bind="value: FirstName" onblur="firstName_OnBlur();" />
</div>
<div>
<label>Last Name:</label>
<input type="text" data-bind="value: LastName" />
</div>
</body>
</html>
上面的示例中有三个特定于 KnockoutJS 的项。其中两个是两个 <input>
HTML 元素上的 data-bind
属性,它们以声明方式将元素绑定到 JavaScript。data-bind
属性将始终由相关元素的属性名称后跟冒号以及属性应绑定的 JavaScript 组成(您也可以在同一个属性中绑定多个属性)。此 JavaScript 可以是 JavaScript 表达式,但通常是对象属性。
第三个特定于 KnockoutJS 的项是在 $(document).ready
函数中调用 ko.applyBindings
函数。applyBindings
函数告诉 KnockoutJS 将 UI 与给定的 JavaScript 对象关联起来。在此示例中,任何 HTML 元素都可以绑定到 ViewModel 对象的任何属性。但是,可以通过将一个元素作为第二个参数传递给 ko.applyBindings
来将多个 JavaScript 对象与页面的不同部分关联起来。默认情况下,当第二个参数为空时,绑定将应用于整个页面。
当您运行上面的示例时,您会注意到“名字”输入元素的 blur 事件处理程序中的警报将始终显示文本框的原始值,在本例中为“Tom”。这是因为上面的示例仅实现了单向数据绑定。实现双向绑定就像调用 KnockoutJS 库上的一个函数一样简单,该函数指示绑定应该是“可观察的”(observable),这意味着当相应的实体更新时,相关实体应该被通知和更新。将 ViewModel
函数替换为以下代码:
function ViewModel()
{
var self = this;
self.FirstName = ko.observable("Tom");
self.LastName = ko.observable("Brady");
return self;
}
如果您希望 UI 元素具有双向绑定,则应该调用 observable
函数。单个参数是默认值。现在,如果您使用修改后的 ViewModel
函数运行示例,firstName_OnBlur
函数中的警报将通过 JavaScript 对象变量显示 <input>
元素的更新值。另外需要注意的是,当您“观察”一个对象时,KnockoutJS 实际上会为底层 JavaScript 对象创建一个函数。因此,要访问对象(或变量)的值,您需要将其视为一个函数,在对象末尾加上“()”。在上面的示例中,对“alert”的调用将如下更改:
alert(theViewModel.FirstName());
设置对象的值也类似,您需要将值作为参数提供给函数,如下所示:
theViewModel.FirstName(‘Bill’);
这是 KnockoutJS 中唯一的“陷阱”,而且我认为它的实现方式是为了支持所有版本的 JavaScript 和浏览器。
任何开发者接下来可能提出的逻辑问题是:“如何实现迭代绑定,以便动态的 HTML 元素列表可以绑定到 JavaScript 对象列表(或数组)?”这几乎同样简单。您不需要调用‘observable’函数,而是调用 KnockoutJS 中的 observableArray
函数,如下面的示例所示。
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript" src="jquery-1_11_2_min.js"></script>
<script type="text/javascript" src="knockout-3.3.0.js" ></script>
<script>
var theViewModel = null;
$(document).ready(function ()
{
theViewModel = ViewModel();
ko.applyBindings(theViewModel);
});
function Car(make, model)
{
var self = this;
self.Make = ko.observable(make);
self.Model = ko.observable(model);
}
function ViewModel()
{
var self = this;
self.Cars = ko.observableArray([
new Car("Honda", "CR-V"),
new Car("Toyota", "Sienna"),
new Car("Ford", "Explorer")
]);
self.onClick = function ()
{
alert(this.Make() + ' ' + this.Model());
};
return self;
}
</script>
</head>
<body>
<div>
<label>Colors:</label>
<table>
<thead>
<tr>
<th>Make</th>
<th>Model</th>
</tr>
</thead>
<tbody data-bind="foreach: Cars">
<tr data-bind="click: onClick">
<td><input data-bind="value: Make" /></td>
<td><input data-bind="value: Model" /></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
此示例中有几点需要注意。<tbody>
元素的 data-bind 中的 foreach
关键字是 KnockoutJS 遍历数组的方式。默认情况下,任何后代 HTML 元素都绑定到数组中的元素,而不是父对象(在本例中为 ViewModel),这解释了为什么我们可以在 data-bind 属性中引用 Make 和 Model 属性。
另一项需要注意的是表行元素的数据绑定中对“click”的引用。KnockoutJS 还允许您将某些事件绑定到数据模型中的函数。在上面的示例中,我们将 ViewModel
(在本例中为父级)中的 onClick
函数与每个表行的 click 事件关联起来。在这种情况下,函数内部由“this”引用的作用域是数组元素本身。
您会在上面的两个示例中注意到,任何 HTML 元素都没有分配“id”或“name”属性。这是因为没有必要。如果您正确地实现了数据绑定,您的 JavaScript 代码就不需要引用 DOM 中的任何元素。相反,您将引用 JavaScript 变量/对象来获取这些元素的值。KnockoutJS 会处理其余的事情。
KnockoutJS 中还有一项我想要指出的功能,名为“计算可观察项”(computed observables),它真正地扩展了该库的实用性和强大功能,以及数据绑定的强大功能。此功能提供了一种使用多个可观察项来实现双向数据绑定的方法。具体来说,它允许您将 JavaScript 函数与 DOM 元素关联起来,而不是变量或对象属性,以便该值可以被“计算”出来,而不是仅仅被分配。
作为计算可观察项的一个例子,我们可以使用上面的第一个演示,并向 ViewModel
对象添加一个 FullName
属性,该属性通过连接姓和名属性(当然,中间有一个空格)来计算得出,如下所示:
function ViewModel()
{
var self = this;
self.FirstName = ko.observable("Tom");
self.LastName = ko.observable("Brady");
self.FullName = ko.computed(function ()
{
return self.FirstName() + " " + self.LastName();
});
return self;
}
通过修改 firstName_OnBlur
事件函数以显示全名,我们可以测试新的 FullName
可观察项,如下所示:
function firstName_OnBlur()
{
alert(theViewModel.FullName());
}
熟悉创建单页 Web 应用程序的开发者应该能够理解 KnockoutJS 库提供的强大功能,尤其是考虑到它的小巧的体积和有限的功能。虽然 KnockoutJS 还提供了更多功能,如自定义绑定、自定义元素和订阅更改,但本文涵盖了最重要和最强大的功能,应该能帮助您立即开始(数据)绑定。