KnockoutJS 3.X API 第四章 数据绑定(2) 控制流foreach绑定
foreach
绑定
foreach绑定主要用于循环展示监控数组属性中的每一个元素
,一般用于table标签中
假设你有一个监控属性数组,每当您添加,删除或重新排序数组项时,绑定将有效地更新UI的DOM-插入或去除相关项目或重新排序现有的DOM元素,不影响任何其他的DOM元素。
当然,也可以配合其他控制流一起适用,例如if
和with
。
示例1:遍历监控属性数组
本例适用foreach绑定,在一个table标签中循环显示监控属性数组的内容
<table>
<thead>
<tr><th>First name</th><th>Last name</th></tr>
</thead>
<tbody data-bind="foreach: people">
<tr>
<td data-bind="text: firstName"></td>
<td data-bind="text: lastName"></td>
</tr>
</tbody>
</table> <script type="text/javascript">
ko.applyBindings({
people: [
{ firstName: 'Bert', lastName: 'Bertington' },
{ firstName: 'Charles', lastName: 'Charlesforth' },
{ firstName: 'Denise', lastName: 'Dentiste' }
]
});
</script>
示例2:添加或删除项目
UI源码:
<h4>People</h4>
<ul data-bind="foreach: people">
<li>
Name at position <span data-bind="text: $index"> </span>:
<span data-bind="text: name"> </span>
<a href="#" data-bind="click: $parent.removePerson">Remove</a>
</li>
</ul>
<button data-bind="click: addPerson">Add</button>
视图模型源码:
function AppViewModel() {
var self = this; self.people = ko.observableArray([
{ name: 'Bert' },
{ name: 'Charles' },
{ name: 'Denise' }
]); self.addPerson = function() {
self.people.push({ name: "New at " + new Date() });
}; self.removePerson = function() {
self.people.remove(this);
}
} ko.applyBindings(new AppViewModel());
备注1:使用$data
如前两个示例中,foreach后面所跟的是要循环的监控属性数组名称,而foreach内部所跟随的是监控属性数组的项目,例如firstName和lastName。
当你想引用监控属性数组本身的时候,就可以使用这个特殊的上下文$data,他所指的就是监控属性数组本身。
例如,你的监控属性数组中的项目没有明确的项目名称:
<ul data-bind="foreach: months">
<li>
The current item is: <b data-bind="text: $data"></b>
</li>
</ul> <script type="text/javascript">
ko.applyBindings({
months: [ 'Jan', 'Feb', 'Mar', 'etc' ]
});
</script>
如何你愿意的话,也可以使用$data来引用监控数组属性中的项目,例如:
<td data-bind="text: $data.firstName"></td>
其实这是多此一举的。因为firstName的默认前缀就是$data,所以一般可以省略不写。
备注2:使用$index、$parent和其他的上下文标记
你可能会发现,在示例2中使用了$index来代替了监控属性数组的索引值(从0开始),当然$index是一个监控属性,他会根据数据的变化而自动变化,就像示例2中展示的一样。
而$parent所代表的是在foreach绑定循环外的某个绑定属性,例如:
<h1 data-bind="text: blogPostTitle"></h1>
<ul data-bind="foreach: likes">
<li>
<b data-bind="text: name"></b> likes the blog post <b data-bind="text: $parent.blogPostTitle"></b>
</li>
</ul>
备注3:使用“as”给foreach绑定项目起个别名
在备注1中,使用$data.varibale的方式访问的监控属性数组的项目,但在有些时候你可以需要给这些项目起个别名,那就是可以使用as,例如:
<ul data-bind="foreach: { data: people, as: 'person' }"></ul>
现在,只要在foreach循环中,使用person,就可以访问数组中的元素了。
也有些嵌套使用的例子,这中会更加复杂一些,例如:
<ul data-bind="foreach: { data: categories, as: 'category' }">
<li>
<ul data-bind="foreach: { data: items, as: 'item' }">
<li>
<span data-bind="text: category.name"></span>:
<span data-bind="text: item"></span>
</li>
</ul>
</li>
</ul> <script>
var viewModel = {
categories: ko.observableArray([
{ name: 'Fruit', items: [ 'Apple', 'Orange', 'Banana' ] },
{ name: 'Vegetables', items: [ 'Celery', 'Corn', 'Spinach' ] }
])
};
ko.applyBindings(viewModel);
</script>
备注4:不使用foreach容器并生产内容
在某些情况下,可能需要复制容器标签的内容,例如生成如下DOM:
<ul>
<li class="header">Header item</li>
<!-- The following are generated dynamically from an array -->
<li>Item A</li>
<li>Item B</li>
<li>Item C</li>
</ul>
像这种情况,我们就无法在ul标签中使用foreach绑定,解决这个问题的方法就是使用无容器的foreach绑定:
<ul>
<li class="header">Header item</li>
<!-- ko foreach: myItems -->
<li>Item <span data-bind="text: $data"></span></li>
<!-- /ko -->
</ul> <script type="text/javascript">
ko.applyBindings({
myItems: [ 'A', 'B', 'C' ]
});
</script>
这里使用虚拟元素容器,<!-- ko -->
和<!-- /ko -->。就想之前章节提到的虚拟绑定一样。
备注5:检测并处理数组变化
当您修改模型数组的内容(通过添加,移动或删除其项),在foreach
绑定使用一个有效的差分算法计算方法当出发生了什么变化的时候。
- 当您添加数组项,
foreach
会使您的模板的新副本,并将其插入到现有的DOM - 当你删除数组项,
foreach
将直接删除相应的DOM元素 - 当你重新排序数组项(保持相同的对象实例),
foreach
通常只要将相应的DOM元素融入自己的新位置
备注6:销毁项目
有时你可能想为数据项目做删除标记,但实际上并不真正删除该项目。这中方式被称为非破坏性的删除。
默认情况下,foreach
绑定将跳过(即隐藏)标记为删除任何数组项。如果你想显示这些项目,使用includeDestroyed
选项。例如,
<div data-bind='foreach: { data: myArray, includeDestroyed: true }'>
...
</div>
备注7:使用动画过渡,提高用户体验
如果您需要在生成的DOM元素运行一些定制逻辑,你可以使用afterRender
/ afterAdd
/beforeRemove
/ beforeMove
/ afterMove
这些回调函数。
下面是一个使用afterAdd的
一个简单的例子,应用经典的“黄色淡出”的效果,以新增项目。它需要的jQuery插件的颜色,使背景色彩的动画。
源码如下:
<ul data-bind="foreach: { data: myItems, afterAdd: yellowFadeIn }">
<li data-bind="text: $data"></li>
</ul> <button data-bind="click: addItem">Add</button> <script type="text/javascript">
ko.applyBindings({
myItems: ko.observableArray([ 'A', 'B', 'C' ]),
yellowFadeIn: function(element, index, data) {
$(element).filter("li")
.animate({ backgroundColor: 'yellow' }, 200)
.animate({ backgroundColor: 'white' }, 800);
},
addItem: function() { this.myItems.push('New item'); }
});
</script>
一些具体的细节
afterRender
-当foreach
第一次初始化执行的回调函数。KO提供下列参数回调:- 插入的DOM元素的数组
- 数据项
afterAdd
-当foreach添加新项目后的回调函数。KO提供下列参数回调:- DOM节点
- 添加的数组元素的索引
- 添加的数组元素
beforeRemove
-当一个数组项已被删除的回调函数。这里最明显的用jQuery的$(domNode).fadeOut()
动画去除相应的DOM节点。KO提供下列参数回调:- 删除一个DOM节点
- 被删除的数组元素的索引
- 删除的数组元素
beforeMove
-当一个数组项在数组中已经改变了位置的回调函数,但之前相应的DOM节点已被移动。需要注意的是beforeMove
适用于所有的数组元素的指标发生了变化,因此,如果你在一个数组的开头插入一个新的项目,然后回调(如果指定)将触发所有其他元素,因为它们的索引位置增加了一个。您可以使用beforeMove
存储在受影响元素的原始屏幕坐标,这样你可以在afterMove
回调动画动作。KO提供下列参数回调:- 可能是移动的DOM节点
- 移动的数组元素的索引
- 移动的数组元素
afterMove
-数组项在数组中已经改变位置的回调函数,KO提供下列参数回调:- 可能已经移动的DOM节点
- 移动的数组元素的索引
- 移动的数组元素
结语
本来想把整个控制流绑定在一节里写完的,但是发现一个foreach就有很多内容,所以控制流绑定将分成多节来写,尽请读者见谅。
KnockoutJS 3.X API 第四章 数据绑定(2) 控制流foreach绑定的更多相关文章
- KnockoutJS 3.X API 第四章 数据绑定(5) 控制流component绑定
本节目录: 一个例子 API 备注1:仅模板式的component 备注2:component虚拟绑定 备注3:传递标记到component绑定 内存管理 一个例子 First instance, w ...
- KnockoutJS 3.X API 第四章 数据绑定(3) 控制流if绑定和ifnot绑定
if绑定目的 if绑定一般是格式是data-bind=if:attribute,if后所跟属性或表达式的值应为bool值(也可以是非bool值,当非空字符串时则为真),if绑定的作用与visible绑 ...
- KnockoutJS 3.X API 第四章 数据绑定(4) 控制流with绑定
with绑定的目的 使用with绑定的格式为data-bind="with:attribute",使用with绑定会将其后所跟的属性看作一个新的上下文进行绑定.with绑定内部的所 ...
- KnockoutJS 3.X API 第四章 数据绑定(1) 文本及样式绑定
目录 本节将介绍六种文本绑定方式: visible绑定 text绑定 html绑定 css绑定 style绑定 attr绑定 可见文本绑定(visible) 使用visible绑定,来控制DOM元素的 ...
- KnockoutJS 3.X API 第四章(13) template绑定
目的 template绑定(模板绑定)使用渲染模板的结果填充关联的DOM元素. 模板是一种简单方便的方式来构建复杂的UI结构 . 下面介绍两种使用模板绑定的方法: 本地模板是支持foreach,if, ...
- KnockoutJS 3.X API 第四章 表单绑定(11) options绑定
目的 options绑定主要用于下拉列表中(即<select>元素)或多选列表(例如,<select size='6'>).此绑定不能与除<select>元素之外的 ...
- KnockoutJS 3.X API 第四章 表单绑定(6) click绑定
目的 click绑定主要作用是用于DOM元素被点击时调用相关JS函数.最常见用于button.input.a元素. 例如: You've clicked timesClick me var viewM ...
- KnockoutJS 3.X API 第四章 表单绑定(7) event绑定
目的 event绑定即为事件绑定,即当触发相关DOM事件的时候回调函数.例如keypress,mouseover或者mouseout等 例如: Mouse over me Details var vi ...
- KnockoutJS 3.X API 第四章 表单绑定(8) submit、enable、disable绑定
submit绑定目的 submit绑定即为提交绑定,通常用于form元素.这种绑定方式会打断默认的提交至服务器的操作.转而提交到你设定好的提交绑定回调函数中.如果要打破这个默认规则,只需要在回调函数中 ...
随机推荐
- Devexpress 汉化
DevExpress是一个比较有名的界面控件套件,提供了一系列的界面控件套件的DotNet界面控件.对于较老的版本(例如之前项目中遇到的dev9),对于汉化(应该说本地化Localization)支持 ...
- java-7311练习(上)
java练习,仅供参考! 欢迎同学们交流讨论. JDK 1.8 API帮助文档 JDK 1.6 API中文文档 Java GUI -------------------------2016-10-23 ...
- Windows 8.1 应用开发文章汇总
Windows 8.1 应用再出发 - C# + XAML 1. Windows 8.1 应用再出发 - 创建我的第一个应用 2. Windows 8.1 应用再出发 - 几种常用控件 3. Win ...
- jquery 模拟 alert 手机,pc,平板 3合一
$.kw = { title : "System information", //默认标题 可修改 speed : 400, //默认速度 可修改 buttonName : &qu ...
- 简单BigDecimal运算精度
项目中遇到了数值运算,如网上所写的,一般有这几个方法: /** * 提供精确的加法运算. * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ publ ...
- PYTHON学习之路_PYTHON基础(10)
学习内容: Python进程与线程 1.线程及线程类 2.线程守护 3.线程等待 4.线程锁 5.信号量 6.timer用法 7.队列 8.事件驱动 9.生产者消费者模型 10.进程及进程同步 11. ...
- Android APK 签名 (转发)
Cordova 3.5 为 Android APK 签名,生成可发布的 APK 程序文件 任侠 2014-06-07 00:04 移动开发 抢沙发 16,288 views 目录 [隐藏] ...
- java word 转 pdf
这里使用jacob将word转pdf,使用的是jacob.jar import java.io.File;import com.jacob.activeX.ActiveXComponent;impor ...
- wlan-mcs来自百度百科
工作原理 802.11n射频速率的配置通过MCS(Modulation and Coding Scheme,调制与编码策略)索引值实现.MCS调制编码表是802.11n为表征WLAN的通讯速率而提出的 ...
- 更改apache网站根目录导致localhost不能访问
使用xampp或wamp安装完集成环境后,更改apache的网站根目录会导致localhost,localhost/phpmyadmin访问不到. 解决方法: 打开apache的配置文件:“../ap ...