KnockoutJS 3.X API 第四章之数据控制流foreach绑定


Posted in Javascript onOctober 10, 2016

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:添加或删除项目

KnockoutJS 3.X API 第四章之数据控制流foreach绑定

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插件的颜色,使背景色彩的动画。

KnockoutJS 3.X API 第四章之数据控制流foreach绑定

源码如下:

<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节点

移动的数组元素的索引

移动的数组元素

以上所述是小编给大家介绍的KnockoutJS 3.X API 第四章之数据控制流foreach绑定,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js 绑定带参数的事件以及手动触发事件
Apr 27 Javascript
JSON+JavaScript处理JSON的简单例子
Mar 20 Javascript
纯JS实现五子棋游戏兼容各浏览器(附源码)
Apr 24 Javascript
jquery中文乱码的多种解决方法
Jun 21 Javascript
鼠标焦点离开文本框时验证的js代码
Jul 19 Javascript
js获取url参数代码实例分享(JS操作URL)
Dec 13 Javascript
jQuery提交多个表单的小技巧
Jul 27 Javascript
js实现的鼠标滚轮滚动切换页面效果(类似360默认页面滚动切换效果)
Jan 27 Javascript
JS中的进制转换以及作用
Jun 26 Javascript
深入浅析knockout源码分析之订阅
Jul 12 Javascript
Vue路由对象属性 .meta $route.matched详解
Nov 04 Javascript
jQuery插件simplePagination的使用方法示例
Apr 28 jQuery
KnockoutJS 3.X API 第四章之数据控制流if绑定和ifnot绑定
Oct 10 #Javascript
KnockoutJS 3.X API 第四章之数据控制流with绑定
Oct 10 #Javascript
JS命令模式例子之菜单程序
Oct 10 #Javascript
KnockoutJS 3.X API 第四章之数据控制流component绑定
Oct 10 #Javascript
KnockoutJS 3.X API 第四章之click绑定
Oct 10 #Javascript
KnockoutJS 3.X API 第四章之事件event绑定
Oct 10 #Javascript
KnockoutJS 3.X API 第四章之表单submit、enable、disable绑定
Oct 10 #Javascript
You might like
PHP cdata 处理(详细介绍)
2013/07/05 PHP
PHP的mysqli_query参数MYSQLI_STORE_RESULT和MYSQLI_USE_RESULT的区别
2014/09/29 PHP
php中二维数组排序问题方法详解
2015/08/28 PHP
php的api数据接口书写实例(推荐)
2016/09/22 PHP
PHP生成(支持多模板)二维码海报代码
2018/04/30 PHP
PHP正则判断一个变量是否为正整数的方法
2019/02/27 PHP
javascript 函数使用说明
2010/04/07 Javascript
Node.js实战 建立简单的Web服务器
2012/03/08 Javascript
仿中关村在线首页弹出式广告插件(jQuery版)
2012/05/03 Javascript
jquery统计用户选中的复选框的个数
2014/06/06 Javascript
关于js里的this关键字的理解
2015/08/17 Javascript
手机端转盘抽奖代码分享
2015/09/10 Javascript
微信小程序 实例开发总结
2017/04/26 Javascript
jQuery遮罩层实例讲解
2017/05/11 jQuery
Mongoose实现虚拟字段查询的方法详解
2017/08/15 Javascript
vue+Element中table表格实现可编辑(select下拉框)
2020/05/21 Javascript
Python天气预报采集器实现代码(网页爬虫)
2012/10/07 Python
python实现系统状态监测和故障转移实例方法
2013/11/18 Python
Python最小二乘法矩阵
2019/01/02 Python
Python比较配置文件的方法实例详解
2019/06/06 Python
python Django的web开发实例(入门)
2019/07/31 Python
python计算二维矩形IOU实例
2020/01/18 Python
Python爬取365好书中小说代码实例
2020/02/28 Python
python实现简单井字棋小游戏
2020/03/05 Python
Keras实现支持masking的Flatten层代码
2020/06/16 Python
解决python中0x80072ee2错误的方法
2020/07/19 Python
手把手教你将Flask应用封装成Docker服务的实现
2020/08/19 Python
python字典通过值反查键的实现(简洁写法)
2020/09/30 Python
Shopee马来西亚:随拍即卖,最佳行动电商拍卖平台
2017/06/05 全球购物
超市实习总结自我鉴定
2013/09/19 职场文书
前台接待岗位职责
2013/12/03 职场文书
关于是否需要写商业计划书
2014/02/07 职场文书
六个一活动实施方案
2014/03/21 职场文书
销售类求职信
2014/06/13 职场文书
电子信息工程专业自荐书
2014/06/24 职场文书
幼儿园六一主持词开场白
2015/05/28 职场文书