首页 > 代码库 > Knockoutjs实例 - 属性绑定(Bindings)之流程控制(Control flow)
Knockoutjs实例 - 属性绑定(Bindings)之流程控制(Control flow)
一、foreach binding
使用此功能可以方便我们循环遍历输出某个数组、集合中的内容。
(1)、循环遍历输出数组
1 | <script type="text/javascript" src=http://www.mamicode.com/"knockout-2.2.0.js"></script> |
2 | |
3 | <table> |
4 | <thead> |
5 | <tr><th>First name</th><th>Last name</th></tr> |
6 | </thead> |
7 | <tbody data-bind="foreach: people"> |
8 | <tr> |
9 | <td data-bind="text: firstName"></td> |
10 | <td data-bind="text: lastName"></td> |
11 | </tr> |
12 | </tbody> |
13 | </table> |
14 | |
15 | <script type="text/javascript"> |
16 | ko.applyBindings({ |
17 | people: [ |
18 | { firstName: ‘Bert‘, lastName: ‘Bertington‘ }, |
19 | { firstName: ‘Charles‘, lastName: ‘Charlesforth‘ }, |
20 | { firstName: ‘Denise‘, lastName: ‘Dentiste‘ } |
21 | ] |
22 | }); |
23 | </script> |
(2)、动态增加和删除遍历节点
1 | <script type="text/javascript" src=http://www.mamicode.com/"knockout-2.2.0.js"></script> |
2 | |
3 | <h4>People</h4> |
4 | <ul data-bind="foreach: people"> |
5 | <li> |
6 | Name at position <span data-bind="text: $index"> </span>: |
7 | <span data-bind="text: name"> </span> |
8 | <a href=http://www.mamicode.com/"#" data-bind="click: $parent.removePerson">Remove</a> |
9 | </li> |
10 | </ul> |
11 | <button data-bind="click: addPerson">Add</button> |
12 | |
13 | <script type="text/javascript"> |
14 | function AppViewModel() { |
15 | var self = this; |
16 | |
17 | self.people = ko.observableArray([ |
18 | { name: ‘Bert‘ }, |
19 | { name: ‘Charles‘ }, |
20 | { name: ‘Denise‘ } |
21 | ]); |
22 | |
23 | self.addPerson = function () { |
24 | self.people.push({ name: "New at " + new Date() }); |
25 | }; |
26 | |
27 | self.removePerson = function () { |
28 | self.people.remove(this); |
29 | } |
30 | } |
31 | |
32 | ko.applyBindings(new AppViewModel()); |
33 | </script> |
(3)、如果我们想要输出数组中的所有元素而不是像例一中使用firstName去指定元素的话,我们可以使用$data来进行输出。比如:
1 | <script type="text/javascript" src=http://www.mamicode.com/"knockout-2.2.0.js"></script> |
2 | |
3 | <ul data-bind="foreach: months"> |
4 | <li> |
5 | The current item is: <b data-bind="text: $data"></b> |
6 | </li> |
7 | </ul> |
8 | |
9 | <script type="text/javascript"> |
10 | ko.applyBindings({ |
11 | months: [‘Jan‘, ‘Feb‘, ‘Mar‘, ‘etc‘] |
12 | }); |
13 | </script> |
当然,我们也可以使用$data来调用数组中具体的元素,比如我们要使用$data调用例1中的firstName的话,我们可以使用$data.firstName来输出firstName。
(4)、使用$index、$parent等其他的上下文属性
我们曾在例2中使用了$index来表示我们数组的下标,$index是Knockoutjs为我们提供的属性,我们可以直接引用,它会随着数组等下标的变化动态变化的,比如如果数组的长度减少了1,$index的值也会跟着减少的。
我们也可以使用$parent来使用foreach元素之外的属性,比如:
1 | <h1 data-bind="text: blogPostTitle"></h1> |
2 | <ul data-bind="foreach: likes"> |
3 | <li> |
4 | <b data-bind="text: name"></b> likes the blog post <b data-bind="text: $parent.blogPostTitle"></b> |
5 | </li> |
6 | </ul> |
这里使用$parent来调用foreach循环体之外的blogPostTitle属性。
(5)、使用"as"为foreach中的元素定义别名
我们可以使用$data来代替数组中的元素,同时我们也可以使用as来为我们要遍历的元素起一个别名。
1 | <script type="text/javascript" src=http://www.mamicode.com/"knockout-2.2.0.js"></script> |
2 | |
3 | <ul data-bind="foreach: { data: categories, as: ‘category‘ }"> |
4 | <li> |
5 | <ul data-bind="foreach: { data: items, as: ‘item‘ }"> |
6 | <li> |
7 | <span data-bind="text: category.name"></span>: |
8 | <span data-bind="text: item"></span> |
9 | </li> |
10 | </ul> |
11 | </li> |
12 | </ul> |
13 | |
14 | <script> |
15 | var viewModel = { |
16 | categories: ko.observableArray([ |
17 | { name: ‘Fruit‘, items: [‘Apple‘, ‘Orange‘, ‘Banana‘] }, |
18 | { name: ‘Vegetables‘, items: [‘Celery‘, ‘Corn‘, ‘Spinach‘] } |
19 | ]) |
20 | }; |
21 | ko.applyBindings(viewModel); |
22 | </script> |
在使用的时候我们要注意,起别名使用的是as:‘category‘而不是as:category。
(6)、在没有绑定属性的情况下使用foreach
有的时候我们想要循环输出一些特殊的内容,比如我们想要输入下面文本中的<li></li>标签:
1 | <ul> |
2 | <li class="header">Header item</li> |
3 | <!-- The following are generated dynamically from an array --> |
4 | <li>Item A</li> |
5 | <li>Item B</li> |
6 | <li>Item C</li> |
7 | </ul> |
如果我们想要循环输出上面代码中的<li></li>标签的话,我们就没有一个可以绑定foreach的元素,此时我们可以通过以下的代码来实现:
1 | <script type="text/javascript" src=http://www.mamicode.com/"knockout-2.2.0.js"></script> |
2 | |
3 | <ul> |
4 | <li class="header">Header item</li> |
5 | <!-- ko foreach: myItems --> |
6 | <li>Item <span data-bind="text: $data"></span></li> |
7 | <!-- /ko --> |
8 | </ul> |
9 | |
10 | <script type="text/javascript"> |
11 | ko.applyBindings({ |
12 | myItems: [‘A‘, ‘B‘, ‘C‘] |
13 | }); |
14 | </script> |
我们使用<!--ko--><!--/ko-->来表示循环的开始和结束,这是一个虚拟的标签,Knockoutjs能够对其中的foreach进行绑定就好像你将foreach绑定到了一个真实的标签上一样。
(7)、默认不显示被标示为删除的元素
有的时候我们要跳过数组中的一些元素,此时这些元素已经被标示为删除,但并没有被真实删除,这些元素当我们使用foreach输出的时候是默认不显示的,如果我们想要这些元素显示的话,我们可以使用includeDestroyed这个选项,比如:
1 | <div data-bind=‘foreach: { data: myArray, includeDestroyed: true }‘> |
2 | ... |
3 | </div> |
二、if binding 和 if not binding
(1)、使用if binding可以控制某个组件动态显示,类似我们之前接触到的visible属性,不过此属性绑定过以后就不能更改,而if binding可以根据相应的条件控制组件是否显示,下面是一个简单的例子:
1 | <script type="text/javascript" src=http://www.mamicode.com/"knockout-2.2.0.js"></script> |
2 | |
3 | <label><input type="checkbox" data-bind="checked: displayMessage" /> Display message</label> |
4 | |
5 | <div data-bind="if: displayMessage">Here is a message. Astonishing.</div> |
6 | |
7 | <script type="text/javascript"> |
8 | ko.applyBindings({ |
9 | displayMessage: ko.observable(false) |
10 | }); |
11 | </script> |
此例根据checkbox是否勾选来控制是否显示下面的一个<div>。
我们也可以使用if来判断某个元素是否为null,如果为null则不会显示,如下:
1 | <script type="text/javascript" src=http://www.mamicode.com/"knockout-2.2.0.js"></script> |
2 | |
3 | <ul data-bind="foreach: planets"> |
4 | <li> |
5 | Planet: <b data-bind="text: name"> </b> |
6 | <div data-bind="if: capital"> |
7 | Capital: <b data-bind="text: capital.cityName"> </b> |
8 | </div> |
9 | </li> |
10 | </ul> |
11 | |
12 | |
13 | <script> |
14 | ko.applyBindings({ |
15 | planets: [ |
16 | { name: ‘Mercury‘, capital: null }, |
17 | { name: ‘Earth‘, capital: { cityName: ‘Barnsley‘} } |
18 | ] |
19 | }); |
20 | </script> |
此例中如果capital为null,则不会进行显示。此时,如果没有if进行判断的话,则在使用capital.cityName时就会出错。
(2)、if not binding的使用方法和if binding的使用方法一样,这里就不作介绍了。
三、with binding
我们可以使用with binding来重新定义一个上下文绑定,比如:
1 | <script type="text/javascript" src=http://www.mamicode.com/"knockout-2.2.0.js"></script> |
2 | |
3 | <h1 data-bind="text: city"> </h1> |
4 | <p data-bind="with: coords"> |
5 | Latitude: <span data-bind="text: latitude"> </span>, |
6 | Longitude: <span data-bind="text: longitude"> </span> |
7 | </p> |
8 | |
9 | <script type="text/javascript"> |
10 | ko.applyBindings({ |
11 | city: "London", |
12 | coords: { |
13 | latitude: 51.5001524, |
14 | longitude: -0.1262362 |
15 | } |
16 | }); |
17 | </script> |
这样我们在使用coords下的latitude和longitude的时候我们就不需要使用coords.latitude来调用了,因为我们使用with:coords来指定了coords的上下文,当我们使用coords下面的属性时就可以直接使用了。
下面提供一个动态交互的例子:
1 | <script type="text/javascript" src=http://www.mamicode.com/"knockout-2.2.0.js"></script> |
2 | |
3 | <form data-bind="submit: getTweets"> |
4 | Twitter account: |
5 | <input data-bind="value: twitterName" /> |
6 | <button type="submit">Get tweets</button> |
7 | </form> |
8 | |
9 | <div data-bind="with: resultData"> |
10 | <h3>Recent tweets fetched at <span data-bind="text: retrievalDate"> </span></h3> |
11 | <ol data-bind="foreach: topTweets"> |
12 | <li data-bind="text: text"></li> |
13 | </ol> |
14 | |
15 | <button data-bind="click: $parent.clearResults">Clear tweets</button> |
16 | </div> |
17 | |
18 | <script type="text/javascript"> |
19 | function AppViewModel() { |
20 | var self = this; |
21 | self.twitterName = ko.observable(‘@StephenFry‘); |
22 | self.resultData = ko.observable(); // No initial value |
23 | |
24 | self.getTweets = function () { |
25 | twitterApi.getTweetsForUser(self.twitterName(), function (data) { |
26 | self.resultData({ |
27 | retrievalDate: new Date(), |
28 | topTweets: data.slice(0, 5) |
29 | }); |
30 | }); |
31 | } |
32 | |
33 | self.clearResults = function () { |
34 | self.resultData(undefined); |
35 | } |
36 | } |
37 | |
38 | ko.applyBindings(new AppViewModel()); |
39 | </script> |
以上就是流程控制的全部内容。
Knockoutjs实例 - 属性绑定(Bindings)之流程控制(Control flow)