Knockoutjs屬性綁定(Bindings)之流程控制(Control flow)


在上一篇《Knockoutjs屬性綁定(Bindings)之控制文本和外觀(Controlling text and appearance)》我們介紹了怎么樣為View層的組件綁定對應的屬性,這篇文章我們接着介紹Knockoutjs的屬性綁定,這次我們主要介紹的是怎么樣通過Knockoutjs來控制組件的流程顯示(比如循環、判斷是否顯示等)。

一、foreach binding

使用此功能可以方便我們循環遍歷輸出某個數組、集合中的內容。

(1)、循環遍歷輸出數組

 1 <script type="text/javascript" src="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="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="#" 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="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="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="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="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="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="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="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>

以上就是流程控制的全部內容。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM