foreach 绑定对于数组中的每一个元素复制一节标记语言, 也就是 html, 并且将这节标记语言和数组里面的每一个元素绑定. 当我们呈现一组 list 数据, 或者一个表格的时候, 十分有用.
如果你绑定的数组是一个 "监控数组" ,observable arra,(和 wpf 里面的 ObservableCollection<T > 差不多). 当你添加或移除, 或者重新排序数组里面的元素的时候, 会动态的更新 UI 界面. 并且此时并不会影响原先的 DOM 元素. 这样比我们直接重新生成一个数组并且绑定元素高效的多.
当然, foreach 也支持嵌套绑定, 或者和其他工作流绑定例如 if 或者 with.
Example 1: 迭代绑定一个数组
对数组中的每一个元素生成一行数据的只读表.
- <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>
Example 2: 给例 1 中的制度表加上一个增加和移除方法
- <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>
要点 1: 用 $data 来指向数组的每一条数据
就像在上面的例子中展示的. foreach 绑定能够指向数组每一条数据的属性. 例如例 1 中的 firstName 和 lastName. 但是, 如果我们想指向数组本身, 应该怎么办, 此时我们可以用 $.data. 在 foreach 绑定中,$data 指的就是数组的当前的元素项.
- <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>
当然, 如果你非要这样做的话, 你也可以给你指向的每一个属性加上一个 $data 前缀. 例如, 你也可以在例 1 中像下面这样写, 虽然这样写没必要, 因为它的默认上下文就是 $data:
<td data-bind="text: $data.firstName"></td>
要点 2: 使用 $index, $parent, 和其他的上下文属性
就像我们在例 2 中看到的那样. 你可一用 $index 来表示数组中当前项从零开始的索引. $index 是一个监控属性, 当数组的项变更的时候 $index 也会自动更新.
同样, 你也可以用 $parent 来指向 foreach 外的数据. 如果 foreach 对应的是 viewmodel 的直接子元素, 那么 $parent 就是指的 viewmodel,$root 是对应根元素, 多层循环嵌套的时候使用 $root
- <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 上下文变量. 但在一些特殊情况下, 给当前项一个别名用起来更方便. 尤其在多层嵌套结构中:
别名使用的语法如下:
<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 元素来使用它.
来源: https://www.cnblogs.com/gavinjay/p/10768378.html