Knockout.js 学习 (八)-- 控制流绑定

foreach binding


使用此功能可以方便我们循环遍历输出某个数组、集合中的内容。

(1)、循环遍历输出数组

<script type="text/javascript" src="knockout-2.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>

(2)、动态增加和删除遍历节点

<script type="text/javascript" src="knockout-2.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>

(3)、如果我们想要输出数组中的所有元素而不是像例一中使用firstName去指定元素的话,我们可以使用$data来进行输出。比如:

<script type="text/javascript" src="knockout-2.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来调用数组中具体的元素,比如我们要使用$data调用例1中的firstName的话,我们可以使用$data.firstName来输出firstName。

(4)、使用$index、$parent等其他的上下文属性

我们曾在例2中使用了$index来表示我们数组的下标,$index是Knockoutjs为我们提供的属性,我们可以直接引用,它会随着数组等下标的变化动态变化的,比如如果数组的长度减少了1,$index的值也会跟着减少的。

我们也可以使用$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>

这里使用$parent来调用foreach循环体之外的blogPostTitle属性。

(5)、使用"as"为foreach中的元素定义别名

我们可以使用$data来代替数组中的元素,同时我们也可以使用as来为我们要遍历的元素起一个别名。

<script type="text/javascript" src="knockout-2.2.0.js"></script>
 
 <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。

(6)、在没有绑定属性的情况下使用foreach

有的时候我们想要循环输出一些特殊的内容,比如我们想要输入下面文本中的<li></li>标签:

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

如果我们想要循环输出上面代码中的<li></li>标签的话,我们就没有一个可以绑定foreach的元素,此时我们可以通过以下的代码来实现:

<script type="text/javascript" src="knockout-2.2.0.js"></script>
 
 <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-->来表示循环的开始和结束,这是一个虚拟的标签,Knockoutjs能够对其中的foreach进行绑定就好像你将foreach绑定到了一个真实的标签上一样。

(7)、默认不显示被标示为删除的元素

有的时候我们要跳过数组中的一些元素,此时这些元素已经被标示为删除,但并没有被真实删除,这些元素当我们使用foreach输出的时候是默认不显示的,如果我们想要这些元素显示的话,我们可以使用includeDestroyed这个选项,比如:

<div data-bind='foreach: { data: myArray, includeDestroyed: true }'> 
    ... 
</div>
二、if binding 和 if not binding

(1)、使用if binding可以控制某个组件动态显示,类似我们之前接触到的visible属性,不过此属性绑定过以后就不能更改,而if binding可以根据相应的条件控制组件是否显示,下面是一个简单的例子:

<script type="text/javascript" src="knockout-2.2.0.js"></script>
 
 <label><input type="checkbox" data-bind="checked: displayMessage" /> Display message</label> 
   
 <div data-bind="if: displayMessage">Here is a message. Astonishing.</div>
   
 <script type="text/javascript">
     ko.applyBindings({
         displayMessage: ko.observable(false)
     });
 </script>

此例根据checkbox是否勾选来控制是否显示下面的一个<div>。

我们也可以使用if来判断某个元素是否为null,如果为null则不会显示,如下:

<script type="text/javascript" src="knockout-2.2.0.js"></script>
 
 <ul data-bind="foreach: planets"> 
     <li> 
         Planet: <b data-bind="text: name"> </b> 
         <div data-bind="if: capital"> 
             Capital: <b data-bind="text: capital.cityName"> </b> 
         </div> 
     </li> 
 </ul> 
   
   
 <script>
     ko.applyBindings({
         planets: [
             { name: 'Mercury', capital: null },
             { name: 'Earth', capital: { cityName: 'Barnsley'} }
         ]
     }); 
 </script>

此例中如果capital为null,则不会进行显示。此时,如果没有if进行判断的话,则在使用capital.cityName时就会出错。

(2)、if not binding的使用方法和if binding的使用方法一样,这里就不作介绍了。

三、with binding

我们可以使用with binding来重新定义一个上下文绑定,比如:

<script type="text/javascript" src="knockout-2.2.0.js"></script>
 
 <h1 data-bind="text: city"> </h1> 
 <p data-bind="with: coords"> 
     Latitude: <span data-bind="text: latitude"> </span>, 
     Longitude: <span data-bind="text: longitude"> </span> 
 </p> 
   
 <script type="text/javascript">
     ko.applyBindings({
         city: "London",
         coords: {
             latitude: 51.5001524,
             longitude: -0.1262362
         }
     }); 
 </script>

这样我们在使用coords下的latitude和longitude的时候我们就不需要使用coords.latitude来调用了,因为我们使用with:coords来指定了coords的上下文,当我们使用coords下面的属性时就可以直接使用了。

下面提供一个动态交互的例子:

<script type="text/javascript" src="knockout-2.2.0.js"></script>
 
 <form data-bind="submit: getTweets"> 
     Twitter account: 
     <input data-bind="value: twitterName" /> 
     <button type="submit">Get tweets</button> 
 </form> 
   
 <div data-bind="with: resultData"> 
     <h3>Recent tweets fetched at <span data-bind="text: retrievalDate"> </span></h3> 
     <ol data-bind="foreach: topTweets"> 
         <li data-bind="text: text"></li> 
     </ol> 
   
     <button data-bind="click: $parent.clearResults">Clear tweets</button> 
 </div>
   
 <script type="text/javascript">
     function AppViewModel() {
         var self = this;
         self.twitterName = ko.observable('@StephenFry');
         self.resultData = ko.observable(); // No initial value 
 
         self.getTweets = function () {
             twitterApi.getTweetsForUser(self.twitterName(), function (data) {
                 self.resultData({
                     retrievalDate: new Date(),
                     topTweets: data.slice(0, 5)
                 });
             });
         }
 
         self.clearResults = function () {
             self.resultData(undefined);
         }
     }
 
     ko.applyBindings(new AppViewModel()); 
 </script>

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

if binding


(1)、使用if binding可以控制某个组件动态显示,类似我们之前接触到的visible属性,不过此属性绑定过以后就不能更改,而if binding可以根据相应的条件控制组件是否显示,下面是一个简单的例子:

<script type="text/javascript" src="knockout-2.2.0.js"></script> <label><input type="checkbox" data-bind="checked: displayMessage" /> Display message</label> <div data-bind="if: displayMessage">Here is a message. Astonishing.</div> <script type="text/javascript"> ko.applyBindings({ displayMessage: ko.observable(false) }); </script>

此例根据checkbox是否勾选来控制是否显示下面的一个<div>。

我们也可以使用if来判断某个元素是否为null,如果为null则不会显示,如下:

<script type="text/javascript" src="knockout-2.2.0.js"></script>

<ul data-bind="foreach: planets">
<li>
Planet: <b data-bind="text: name"> </b>
<div data-bind="if: capital">
Capital: <b data-bind="text: capital.cityName"> </b>
</div>
</li>
</ul>
<script>
ko.applyBindings({
planets: [
{ name: 'Mercury', capital: null },
{ name: 'Earth', capital: { cityName: 'Barnsley'} }
]
});
</script>

此例中如果capital为null,则不会进行显示。此时,如果没有if进行判断的话,则在使用capital.cityName时就会出错。

If Binding

  • 与visible binding类似,都可以控制一段内容是否出现在页面中。
  • 与visible不同的是,if binding是真正的控制Html标签是否出现在DOM中,如果绑定的值为false,则Html标签不会出现在页面中。
  • if绑定会修改DOM结构,所以出于性能考虑,不应该频繁修改if的绑定值。(这种情况应该使用visible binding)
  • 如果与observable或者computed属性绑定,则会产生双向绑定效果。

ifnot binding


Purpose

The ifnot binding is exactly the same as the if binding, except that it inverts the result of whatever expression you pass to it. For more details, see documentation for the if binding

.ifnot 绑定和if 绑定基本差不多,与if绑定正好相反 不多说了

Note: “ifnot” is the same as a negated “if”

The following markup:

<div data-bind="ifnot: someProperty">...</div>

… is equivalent to the following:

<div data-bind="if: !someProperty()">...</div>

with binding


我们可以使用with binding来重新定义一个上下文绑定,比如:

<script type="text/javascript" src="knockout-2.2.0.js"></script> <h1 data-bind="text: city"> </h1> <p data-bind="with: coords"> Latitude: <span data-bind="text: latitude"> </span>, Longitude: <span data-bind="text: longitude"> </span> </p> <script type="text/javascript"> ko.applyBindings({ city: "London", coords: { latitude: 51.5001524, longitude: -0.1262362 } }); </script>

这样我们在使用coords下的latitude和longitude的时候我们就不需要使用coords.latitude来调用了,因为我们使用with:coords来指定了coords的上下文,当我们使用coords下面的属性时就可以直接使用了。

下面提供一个动态交互的例子:

<script type="text/javascript" src="knockout-2.2.0.js"></script> <form data-bind="submit: getTweets"> Twitter account: <input data-bind="value: twitterName" /> <button type="submit">Get tweets</button> </form> <div data-bind="with: resultData"> <h3>Recent tweets fetched at <span data-bind="text: retrievalDate"> </span></h3> <ol data-bind="foreach: topTweets"> <li data-bind="text: text"></li> </ol> <button data-bind="click: $parent.clearResults">Clear tweets</button> </div> <script type="text/javascript"> function AppViewModel() { var self = this; self.twitterName = ko.observable('@StephenFry'); self.resultData = ko.observable(); // No initial value self.getTweets = function () { twitterApi.getTweetsForUser(self.twitterName(), function (data) { self.resultData({ retrievalDate: new Date(), topTweets: data.slice(0, 5) }); }); } self.clearResults = function () { self.resultData(undefined); } } ko.applyBindings(new AppViewModel()); </script>

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

posted @ 2013-12-19 09:35  风舞烟  阅读(884)  评论(0编辑  收藏  举报