KnockOut 绑定之foreach绑定(mvc+knockout)

什么时候使用foreach绑定

foreach绑定对于数组中的每一个元素复制一节标记语言,也就是html,并且将这节标记语言和数组里面的每一个元素绑定。当我们呈现一组list数据,或者一个表格的时候,十分有用。

如果你绑定的数组是一个"监控数组" ,observable array,(和wpf里面的ObservableCollection<T>差不多)。当你添加或移除,或者重新排序数组里面的元素的时候,会动态的更新UI界面。并且此时并不会影响原先的DOM元素。这样比我们直接重新生成一个数组并且绑定元素高效的多。

当然,foreach也支持嵌套绑定,或者和其他工作流绑定例如if 或者with。

Example 1: 迭代绑定一个数组

对数组中的每一个元素生成一行数据的只读表。

@{
    Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/knockout-3.2.0.js"></script>

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

效果如下:

First name Last name
Bert Bertington
Charles Charlesforth
Denise Dentiste

Example 2: 给例1中的制度表加上一个增加和移除方法

下面这个例子展示了,如果你绑定的数组是一个监控数组,那么这个UI界面将会和数组的改变同步。

People

  • Name at position 0: Bert Remove
  • Name at position 1: Charles Remove
  • Name at position 2: Denise Remove

Add

@{
    Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/knockout-3.2.0.js"></script>

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

<script type="text/javascript">
    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());
</script>

参数

    • 主参数
    • 给foreach传过去你希望迭代的数组。对于每一个数组元素foreach绑定会输出一段超文本标记语言。
    • 你也可以给foreach绑定传递一个含有data属性的 的你想要去迭代的javascript字面量,这个字面量也可以有其它属性, 例如 afterAdd 或者includeDestroyed ,可以看接下来的例子。
    • 如果你绑定的是一个监控数组,对数组内容的增加或者移除foreach绑定将会在UI界面上增加或者移除dom元素。
    • 其它参数

要点1:  用 $data来指向数组的每一条数据

就像在上面的例子中展示的。foreach绑定能够指向数组每一条数据的属性。例如例1中的firstName 和lastName.但是,如果我们想指向数组本身,应该怎么办,此时我们可以用$.data.在foreach绑定中,$data指的就是数组的当前的元素项。

@{
    Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/knockout-3.2.0.js"></script>
<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>

效果如下

  • The current item is: Jan
  • The current item is: Feb
  • The current item is: Mar
  • The current item is: etc

当然,如果你非要这样做的话, 你也可以给你指向的每一个属性加上一个 $data前缀.例如,你也可以在例1中像下面这样写,虽然这样写没必要,因为它的默认上下文就是$data:

<td data-bind="text: $data.firstName"></td>

要点 2: 使用$index, $parent, 和其他的上下文属性

就像我们在例2 中看到的那样。你可一用$index 来表示数组中当前项从零开始的索引。 $index是一个监控属性,当数组的项变更的时候$index也会自动更新。

同样,你也可以用$parent来指向foreach外的数据。如果foreach对应的是viewmodel的直接子元素,那么$parent就是指的viewmodel

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

更多关于 $index和$parent的资料可以去看 binding context properties.

要点 3: 用as 给foreach项赋值一个别名

就想在要点1里面描述的那样。我们可以引用每一个数组项用  $data 上下文变量。但在一些特殊情况下,给当前项一个别名用起来更方便。尤其在多层嵌套结构中:

别名使用的语法如下:

<ul data-bind="foreach: { data: people, as: ‘person‘ }"></ul>

现在在foreach循环的任何地方,绑定都可以根据person指向当前people的数组项。这种语法在多层foreach嵌套的场景中非常有用。例如:

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

注意: 记得通过as给别名 赋值的时候,传过去一个字符串‘category‘, 不是as: category), 因为我们是要给变量起一个别名,而不是传递一个标识符变量过去。

Note 4: 没有一个容器元素的时候使用foreach

在一些情况下,你想要通过foreach绑定一段标记语言html,但是没有供foreach绑定的元素。例如下面这张情景:

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

这种情况下没有任何元素可供foreach绑定。你不能放到ul里面,因为这时候会把header也放到复制的循环里面去。你也不能放其它的元素在ul里面,因为ul里面只允许放<li>元素。

要想处理这种情况。我们可以用无容器绑定语法。这中情况是依赖于html的注释标签。如下:

<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 --> 注释作为标签的开始和结束,定义了一个虚元素来包含我们需要重复引用的标记语言在里面,knockout理解这种虚元素语法。我们可以就当真的有一个html元素来使用它。

要点 5: 数组的改变如何被检测和处理

当你修改绑定煮熟的值时,例如增加删除移动, foreach绑定用一个有效的区分语法来检测出哪一项被改变了。所以,能够去改变预知匹配的dom元素,这以为着knockout可以处理任意的和并和同时的改变

  • 当我么增加一个数组项的时候, foreach 将会根据我们的模板绘制一个新的dom元素想插入到原先的dom元素中。
  • 当我们删除一个项目的时候, foreach 将会移除相关的dom元素。
  • 当我们移动相关的数组项时), foreach 将只会移动相关的dom元素。

注意,重新排列时候的排列不是肯定的:需要确保我们的元素想操作足够快。,它被优化只是检测少量的数组项变动。当同时变动的元素很多的时候,knockout会选择执行删除然后重新的添加的方式,而不是只是移动dom元素。

要点 6: 删除项默认被隐藏

有时你想要将一个数组项标记为删除, 但并不是真的删除. 这就是我们所说的“非毁灭式删除”. 对于更多的资料可以看the destroy function on observableArray.

默认的foreach 绑定将会只是将被删除的项隐藏。如果你想看并非真正被删除的项,你可以用 includeDestroyed参数. 例如

<div data-bind=‘foreach: { data: myArray, includeDestroyed: true }‘>
    ...
</div>

要点 7: dom元素后期处理或生成动画

如果我们想在生成dom元素的时候添加更多自定义的逻辑我们可以用,afterRender/afterAdd/beforeRemove/beforeMove/afterMove 这些回调函数

注意: 这些回调函数时为了生成list改变的时候的动画。对于一些跟复杂的需求,我们可以用自定义绑定 custom binding 。

@{
    Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.color-2.1.2.js"></script>
<script src="~/Scripts/knockout-3.2.0.js"></script>

<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 模板元素被插入document 的时候被调用。第一次初始化和后续每次添加的时候都会调用这个回调函数。会传递下面的参数给回调函数:

    1. 插入的dom元素数组
    2. 被绑定的数据元素本身
  • afterAdd —和 afterRender很像,不过只有增加元素的时候被调用,第一次初始化的时候不会被调用.常用来执行元素的淡入$(domNode).fadeIn() 该函数接收下列参数:
    1. 增加的dom节点。
    2. 增加元素的索引
    3. 增加的数组元素
  • beforeRemove —当一个数组元素被移除,但是相关的dom元素还没有被移除的时候调用,.  a beforeRemove 常用来执行dom节点的淡出. $(domNode).fadeOut() 这种情况下knockout不知道你要设置多久的淡出时间,所以对于元素的移除,要在该回调函数里面手动移除。该函数接收以下参数:
    1. 应该被移除的数组节点
    2. 被移除数组元素的索引
    3. 移除的数组元素
  • beforeMove —当一个数组元素改变了位置,但是相关的dom元素还没有被移动的时候执行. 注意beforeMove 将会对所有索引改变的数组元素有效。 所以,如果你在数组元素的开始位置插入一项,那么aftermove回调函数会对所有的元素有效。因为所有元素的索引都加1改变。我们可以用. beforeMove 来记录为移动前元素值,然后在aftermove中使用.该回调函数接收以下参数:
    1. 打算移动的dom节点
    2. 移动的数组元素的索引
    3. 移动的数组元素
  • afterMove —在数组元素的位置被改变后调用, 并且是在foreach更新了dom元素后调用 注意afterMove 将会对所有索引改变的数组元素有效。 所以,如果你在数组元素的开始位置插入一项,那么aftermove回调函数会对所有的元素有效。因为所有元素的索引都加1改变。该回调函数接收以下参数:
    1. 一个已经被移除的dom 节点
    2. 移除数组元素的索引
    3. 移除的数组 元素

更多的例子afterAdd and beforeRemove 请看 animated transitions.

knockout分页demo: http://www.cnblogs.com/santian/p/4342777.html

KnockOut官网:http://knockoutjs.com/documentation/foreach-binding.html

本文地址:http://www.cnblogs.com/santian/p/4379445.html

博客地址:一天两天三天

转载请以超链接形式标明文章原始出处。

时间: 2024-10-08 15:36:12

KnockOut 绑定之foreach绑定(mvc+knockout)的相关文章

Knockout学习之控制流绑定器

控制流绑定器 “foreach”绑定 顾名思义,通过该绑定我们就可以将监控数组循环输出到页面中去了,当然我们还是先来段简单的示例,仅仅只是输出监控数组: 1 <ul data-bind="foreach:people" > 2 <li data-bind="text:Name"></li> 3 </ul> 4 5 6 <script type="text/javascript"> 7 8

Knockout官网实例在MVC下的实现-01,实现Hello world

本篇使用Knockout在MVC下实现"Hello World",对应的官网实例在这里. View视图 Knockout的一个特点是:声明式绑定,即Declarative bindings.暂且不管业务逻辑,先把关注点放在界面UI上,即"MVVM"模式中的第二个"V", 也就是View视图.根据Knockout的语法,创建如下界面: <div> <p>First name:<input data-bind="

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

foreach绑定 foreach绑定主要用于循环展示监控数组属性中的每一个元素,一般用于table标签中 假设你有一个监控属性数组,每当您添加,删除或重新排序数组项时,绑定将有效地更新UI的DOM-插入或去除相关项目或重新排序现有的DOM元素,不影响任何其他的DOM元素. 当然,也可以配合其他控制流一起适用,例如if和with. 示例1:遍历监控属性数组 本例适用foreach绑定,在一个table标签中循环显示监控属性数组的内容 <table> <thead> <tr&g

KnockoutJS学习笔记10:KonckoutJS foreach绑定

KnockoutJS foreach绑定用来处理数组,通常用来将一个数组绑定到一个列表或者table中.在foreach绑定中,我们可以使用if.with等嵌套绑定. 示例代码: <table> <thead> <tr><th>First name</th><th>Last name</th></tr> </thead> <tbody data-bind="foreach: peop

foreach绑定

目的 foreach可以将一个数组中的实体循环的进行绑定.这在将一个list显示成table时非常有用. 假设数组是observable的,当在绑定后做了add, remove,或者重新排序后,绑定会找到相应的元素做新增.删除或者排序,而不会影响其他不相关的DOM元素.这比重新生成整个foreach的输出要高效的多. 当然,你也可以任意的使用其他控制语句如if和with来嵌套foreach绑定. 例1:遍历数组 示例使用foreach循环一个数组实体展示成一个只读的table <table>

KnockoutJS 3.X API 第四章 数据绑定(3) 控制流if绑定和ifnot绑定

if绑定目的 if绑定一般是格式是data-bind=if:attribute,if后所跟属性或表达式的值应为bool值(也可以是非bool值,当非空字符串时则为真),if绑定的作用与visible绑定的作用类似.可控制DOM的显示与隐藏,不一样的地方是,if绑定是物理删除或添加DOM元素. 示例1 该例展示IF绑定的动态删除添加DOM: Display message Here is a message. Astonishing. UI源码: <label><input type=&q

细说 Web API参数绑定和模型绑定

今天跟大家分享下在Asp.NET Web API中Controller是如何解析从客户端传递过来的数据,然后赋值给Controller的参数的,也就是参数绑定和模型绑定. Web API参数绑定就是简单类型的绑定,比如:string,char,bool,int,uint,byte,sbyte,short,ushort,long, float这些基元类型.模型绑定就是除此之外的复杂类型的绑定.大家都知道在MVC中模型绑定都是通过默认的DefaultModelBinder来绑定的,没有Get请求和P

前期绑定和后期绑定

程序绑定的概念:绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来.对java来说,绑定分为静态绑定和动态绑定:或者叫做前期绑定和后期绑定 静态绑定:在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现.例如:C.针对java简单的可以理解为程序编译期的绑定:这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定 动态绑定:后期绑定:在运行时根据具体对象的类型进行绑定.若一种语言实现了后期绑定,同时必 须提供一些机制,可在运行期间判断对

什么样的局域网需要IP-MAC绑定?IP-MAC绑定的好处。

1. 为什么要进行IP-mac绑定? IP-MAC绑定是网络管理的一个重要手段,在局域网内启用IP-MAC绑定,可以给您带来如下好处: 只有通过绑定的设备才可以接入网络,从而有效的防止了私接设备. 大部分上网和流控策略都是基于IP地址的,需要绑定IP和MAC才可以更好的应用上网策略. 实现有效的上网记录和上网统计.如果不绑定,那么记录统计不能有效的定位到具体用户. 节省IP资源,防止IP盗用. 减少ARP攻击,杜绝IP地址冲突,从而提高网络的稳定性. 所以,对于企业的办公局域网来说,IP-MAC