ti8淘汰赛
KnockoutJS是基于Model-View-ViewModel模式的优雅JavaScript库,可帮助我们轻松创建丰富的用户界面。 如果您开发的应用程序具有可在基础数据模型发生更改时动态更新的部分,那么Knockout确实可以为您提供帮助。 Knockout中的两种数据绑定和模板功能使实现动态视图的过程变得轻而易举。 本教程将使您开始使用Knockout,并向您展示如何在自己的项目中使用它。
安装淘汰赛
安装Knockout只需在HTML页面中包含一个小JavaScript文件。 前往Knockout网站并下载正式版。 另外,您可以包括CDN的淘汰赛。 只需将以下<script>
标记放在HTML文档中即可。
<script type='text/javascript' src='http://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js'></script>
MVVM模式
为了有效地使用Knockout,您必须首先了解MVVM模式是什么。 如果您已经了解了MVVM模式,则可以跳到下一部分。
模型: MVVM中的M代表模型,通常是应用程序保留的业务数据。 在大多数情况下,您最初将通过Ajax调用从服务器读取此数据并将其显示在UI上。 例如,如果要从服务器检索笔记列表,则可以向服务器发出Ajax GET
请求。
视图:在淘汰赛中,视图只是显示ViewModelHTML页面(我们将介绍)。 只要这些ViewModel发生更改,链接到ViewModel的视图的特定部分也会更改。
ViewModel:简单来说,ViewModel是由View呈现的模型。 它是数据及其上支持的操作的纯代码表示。 ViewModel通常不持久保存,并保存用户正在使用的未保存的更改。 如果要稍后保存更改,则可以将此数据发布回服务器。 在淘汰赛中,ViewModels由POJO(普通的旧JavaScript对象)实现。 例如,如果您要显示待办事项列表,则您的ViewModel可能会保存此类便笺对象的列表,并公开一些用于修改/添加便笺的函数。
入门
作为学习Knockout的第一步,让我们研究一下ViewModels和数据绑定。 以下代码段创建了一个简单的ViewModel:
function NameViewModel() {
this.name = 'John Doe';
}
或者,可以将ViewModel编写为对象,如下所示。
var nameViewModel = {
name: 'John Doe'
}
现在,在HTML中,您只需要编写以下声明性绑定即可与ViewModel的name
属性连接。
Hello, <span data-bind="text:name"></span>
此代码段仅将UI与ViewModel的name
属性连接。 在这里, name
的值是span
标记中的innerHTML
ed。 现在,作为最后一步,我们需要告诉Knockout name
属性属于哪个ViewModel。 为此,只需添加以下代码。
ko.applyBindings(new NameViewModel());
这会导致淘汰赛执行数据绑定。 结果,在HTML中,我们在span
元素内看到name
的值。
注意:在复杂的应用程序中,您可能有多个ViewModel,而不仅仅是一个。 在那种情况下,您可以通过将第二个参数传递给ko.applyBindings()
来将特定的ViewModel绑定到UI的特定部分。 下面是一个示例。
ko.applyBindings(new ContactViewModel(), document.getElementById('contacts-area'));
ko.applyBindings(new NoteViewModel(), document.getElementById('notes-area'));
最后要注意的一点是,在文档准备就绪之前,不应调用ko.applyBindings()
。 如果使用的是jQuery,则将调用包装在$(document).ready()
。 在VanillaJS中 ,您可以使用DOMContentLoaded
事件处理程序。
与Observable的双向绑定
我们刚刚学习了如何将模型属性绑定到UI。 但是,我们可以走得更远,使它变得动态。 使用可观察对象,您可以将属性绑定到UI上,这有另一个好处–每当ViewModel属性更改时,UI就会自动更新。 此外,我们可以使用Knockout的声明性绑定功能,以便只要UI中的值(例如,输入字段值)发生更改,ViewModel属性也将更新。 这样可以使ViewModel和View保持同步。
要根据属性值更新视图,需要使该属性可观察。 这很简单。 只需修改我们之前的代码,如下所示:
function NameViewModel() {
this.name = ko.observable(''); //initially empty
}
现在,只要name
属性更改,我们的视图就会更新。 现在,让我们将输入字段添加到HTML并将其绑定到name
以便每当用户在其中键入内容时,属性都会更改,并且我们会在span
标记中看到更新的值。
<input type="text" data-bind="value:name,valueUpdate:'input'" placeholder="start typing a name here"/>
Hello, <span data-bind="text:name"></span>
在这里,我们利用了Knockout的声明性绑定语法。 在data-bind
属性中,该value
指示我们要绑定到的属性。 第二个参数valueUpdate
指定何时更新ViewModel属性。 正如我们将其设置为'input'
,只要输入字段值更改,ViewModel中的属性就会更新。 要查看此功能的实际效果,请看一下该插头。
每当任何可观察的值更改时,您还可以获取通知。 以下示例显示了如何使用subscribe()
函数完成此操作。
function NameViewModel() {
this.name = ko.observable('');
this.name.subscribe(function(newVal) {
console.log(newVal); //logs whenever the value changes
});
}
使用计算的可观察物
有时,您可能希望使用其派生属性的值取决于一个或多个其他属性。 如果要在视图中显示此派生属性,则逻辑上每当它依赖于更改时就对其进行更新。 为此,我们需要一个可计算的可观察对象,其创建方式如下:
function ContactViewModel() {
this.phone = ko.observable();
this.email = ko.observable();
this.contactInfo = ko.computed(function() {
return this.phone() + ", " + this.email();
}, this);
}
![](https://i-blog.csdnimg.cn/blog_migrate/70f75972597b7f1331a6f72d35798541.png)
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
现在,在视图中,我们可以使用以下HTML绑定计算的可观察对象。
Contact Information: <span data-bind="text: contactInfo"></span>
通过查看传递给ko.compute()
的回调(或评估函数ko.compute()
,Knockout知道计算出的可观察对象所依赖的可观察对象。 每当它们中的任何一个发生变化时,您的评估函数都会自动被调用。
ko.compute()
的第二个参数是应在评估函数内用作this
对象的对象。 值得指出的是,您可以使用闭包实现相同的功能,如下所示。
function ContactViewModel() {
var self = this;
self.phone = ko.observable();
self.email = ko.observable();
self.contactInfo = ko.computed(function() {
return self.phone() + ", " + self.email();
});
}
最后要注意的是,当使属性可观察时,您不应再在代码中直接访问它们。 相反,我们需要像函数那样调用它们。 这就是在上一个示例中使用函数调用检索phone
和email
的值的原因。 要设置可观察值,只需将新值作为函数参数传递(即self.phone(4657324573)
)。
可观察阵列
每当我们要检测单个ViewModel属性中的更改时,都可以使用可观察对象。 但是,在许多情况下,我们有兴趣了解对象集合是否已更改。 在这种情况下,我们可以使用通过以下代码创建的可观察数组。
function NotesViewModel() {
this.notes = ko.observableArray();
}
创建可观察数组之后,通常将遍历所有项并将其显示在UI上。 每当您将新项目添加到集合中或将其删除时,视图都会自动更新。
您还可以像这样将初始值传递给可观察数组:
this.notes = ko.observableArray(['one', 'two', 'three']);
您还可以执行各种数组操作,例如pop()
, push()
, shift()
, unshift()
, reverse()
, sort()
, splice()
等。很好,不是吗?
一个简单的淘汰赛应用程序
在本节中,我们将创建一个带有简单UI的Knockout应用程序,用于管理手机数据。 添加新手机后,详细信息将显示在表格中。 用户还可以从表中删除项目。 看看展示最终结果的演示 !
在继续之前,请确保同时安装了Knockout和Knockout映射插件。 稍后我将讨论映射插件。 现在,只需在Knockout库之后包括以下内容即可:
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"/>
第1步
假设每个手机将具有三个属性: name
, os
和price
。 我们需要创建一个ViewModel,并添加一些示例电话详细信息:
function PhonesViewModel() {
var self = this;
self.phones = ko.observableArray([{
name: 'Sony Xperia Z1',
os: 'Android',
price: 599
}, {
name: 'Apple iPhone 5S',
os: 'iOS',
price: 199
}, {
name: 'Google Nexus 5',
os: 'Android',
price: 299
}]);
}
如您所见,我们创建了一个可观察的数组,其中包含手机详细信息。 我们将在视图上遍历这些数组元素。
第2步
创建一个对象来保存在视图中输入的当前电话详细信息。 我们需要将以下代码添加到我们的ViewModel中。
self.currentPhone = ko.mapping.fromJS({
name: '',
os: '',
price: ''
});
currentPhone
对象保存在UI上输入的电话详细信息。 我们将属性name
, os
和price
绑定到HTML上的输入字段。 添加电话详细信息后,我们也希望清除这些字段。 为了清除这些字段,我们需要使这些属性可观察,然后在添加电话的功能中清除它们。 Knockout映射插件中的ko.mapping.fromJS()
函数自动使对象属性可观察,因此我们不必为每个属性编写ko.observable()
。
第三步
接下来,我们想提供一种将新手机添加到列表中的方法。 只需将以下函数添加到我们的ViewModel中即可。
self.addPhone = function() {
self.phones.push(ko.mapping.toJS(self.currentPhone));
self.currentPhone.name('');
self.currentPhone.os('');
self.currentPhone.price('');
};
ko.mapping.toJS()
创建并返回具有常规属性而非可观察对象的对象。 然后,我们将此对象添加到电话列表中,并清除currentPhone的属性,以使其反映在视图中。
第4步
在此步骤中,我们将允许用户从列表中删除电话。 使用以下功能可完成此操作。
self.removePhone = function() {
self.phones.remove(this);
};
在这里, this
代表我们表中将要删除的特定行。
第5步
接下来,添加以下标记:
<table>
<thead>
<tr>
<td></td>
<th>Name</th>
<th>OS</th>
<th>Price</th>
</tr>
</thead>
<tbody data-bind="foreach: phones">
<tr>
<td><a href="#" data-bind="click: $parent.removePhone">Remove</a></td>
<td data-bind="text: name"></td>
<td data-bind="text:os"></td>
<td data-bind="text:price"></td>
</tr>
</tbody>
</table>
<hr/>
<h3>Add a new Phone</h3>
<form data-bind="submit:addPhone">
<input type="text" data-bind="value:currentPhone.name,valueUpdate:'input'" placeholder="Phone Name" />
<br/>
<input type="text" data-bind="value:currentPhone.os,valueUpdate:'input'" placeholder="OS" />
<br/>
<input type="text" data-bind="value:currentPhone.price,valueUpdate:'input'" placeholder="Price" />
<br/>
<button type="submit">Add</button>
</form>
在此标记中,我们使用了foreach
数据绑定,该数据绑定遍历电话列表并显示它们。 我们还使用了click
绑定从表中删除了一个项目。 这将在我们的ViewModel上调用removePhone()
函数。 当我们进入foreach
绑定内部时,便为我们创建了一个新的上下文。 为了获得对根ViewModel的引用,我们使用$parent
。
接下来要注意的是submit
绑定。 单击提交按钮时,这可以防止通常的表单提交过程。 这使我们可以指定将调用的自定义函数。 在这种情况下,将调用addPhone()
,以添加新电话。 在表单内部,我们有三个输入字段,它们与currentPhone
属性同步。 因此,只要有人按下“提交”按钮,我们就会在currentPhone
对象中获得详细信息,只需将其发送到我们的电话列表中即可。
第6步
使用以下代码激活淘汰赛,并观察一切正常!
ko.applyBindings(new PhonesViewModel());
结论
KnockoutJS绝对是使用MVVM模式构建动态UI的绝佳框架。 本教程介绍了库的基础知识,但是肯定有一些高级概念需要您注意。 以下资源可以为您提供帮助:
- 计算的观测值的详细信息 。
- 详细的声明式绑定语法 。
- 使用JSON 。
可以在GitHub上找到本文演示的完整源代码。
ti8淘汰赛