首页 > 代码库 > 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         var appViewModel = function () { 9             this.people = ko.observableArray([10                 { Name: "y-z-f" },11                 { Name: "z-n" },12                 { Name: "y-z-c" }13             ]);14         }15 16         ko.applyBindings(new appViewModel());17 </script>

 

 

通过这种方式我们可以将后台的表格改成采用ajax加载和翻页,但是还会有对应的删除等等操作,而且删除操作我们需要获取当前所选的项,获取这非常简单就可以解决,但是KO已经提供给我们现成的方式,那就是执行环境,通过$parent我们可以在后面通过点语法使用我们在视图模型中定义的函数,并且上下文环境自动就是当前所选的项,其实这个上下文其实就是你的函数中使用的this指向的是所选的数组的一项,下面我们将上面的代码改写,提供一个按钮可以在输出Name:

 1 <ul data-bind="foreach:people" > 2     <li> 3         <span data-bind="text:Name" ></span> 4         <button type="button" data-bind="click:$parent.show">点我</button> 5     </li> 6 </ul> 7  8  9     <script type="text/javascript">10 11         var appViewModel = function () {12             this.people = ko.observableArray([13                 { Name: "y-z-f" },14                 { Name: "z-n" },15                 { Name: "y-z-c" }16             ]);17             this.show = function () {18                 alert(this.Name);19             }20         }21 22         ko.applyBindings(new appViewModel());23 </script>

 

 

读者可以在show函数中下断点,可以看到this的值是所选的那一项,是不是瞬间感觉很多事立马就简单了。但是我们还没有解决一个问题,如果上面只是简单的数组,我们该怎么输出里面的值呢?当然KO的设计者人不可能想不到这个,我们提供了$data用来访问,比如下面所示的代码:

 1 <ul data-bind="foreach:people" > 2     <li> 3         <span data-bind="text:$data" ></span> 4     </li> 5 </ul> 6  7  8     <script type="text/javascript"> 9 10         var appViewModel = function () {11             this.people = ko.observableArray([12                 "y-z-f",13                 "z-n",14                  "y-z-c"15             ]);16         }17 18         ko.applyBindings(new appViewModel());19 </script>

 

 

顺利输出内容,当然这里一样也可以使用$parent,当然在前面那个例子里$data一样也可以使用,在不嵌套的情况下这样做是没问题的,如果出现嵌套情况,并且外层循环和内层循环都存在一个Name属性就会有点绕了,所以KO还提供了as可以让我们起另外一个名字,而不使用$data,比如下面的嵌套循环:

 1 <ul data-bind="foreach:{data:people,as : ‘P‘}" > 2     <li> 3         <span data-bind="text:P.Name" ></span> 4         <ul data-bind="foreach: { data: P.Names, as: ‘S‘ }" > 5             <li> 6                 <span data-bind="text:S.Name" ></span> 7             </li> 8         </ul> 9     </li>10 </ul>11 12     <script type="text/javascript">13 14         var appViewModel = function () {15             this.people = ko.observableArray([16                 { Name: "aaaa", Names: [{ Name: "a1" }, { Name: "a2" }] },17                 { Name: "bbbb", Names: [{ Name: "b1" }, { Name: "b2" }] }18             ]);19         }20 21         ko.applyBindings(new appViewModel());22 </script>

 

 

这样看就清爽多了,而且在子循环里面一样可以使用父循环中的P,如果我想ul的第一个li是固定的,但是foreach是会把ul里面所有的li重新创建的,当然我们可以使用另外一个语法:

 1 <ul> 2     <li> 3         aaaaaa 4     </li> 5     <!--ko foreach:{data:people,as : ‘P‘} --> 6     <li> 7         <span data-bind="text:P.Name" ></span> 8         <ul data-bind="foreach: { data: P.Names, as: ‘S‘ }" > 9             <li>10                 <span data-bind="text:S.Name" ></span>11             </li>12         </ul>13     </li>14     <!--/ko -->15 </ul>16 17 18     <script type="text/javascript">19 20         var appViewModel = function () {21             this.people = ko.observableArray([22                 { Name: "aaaa", Names: [{ Name: "a1" }, { Name: "a2" }] },23                 { Name: "bbbb", Names: [{ Name: "b1" }, { Name: "b2" }] }24             ]);25         }26 27         ko.applyBindings(new appViewModel());28 </script>

 

 

其中的语法在之前我们已经使用过了,所以在这里出现也不会奇怪,唯一的不同就是结束标签要放到需要循环的标签的尾部。

 

在之前学习监控属性的时候我们学习了destroy方法,但是这个方法并不会真的删除数据,而是会设置一个特殊的属性,那么问题就来了,如果我们通过destroy删除一项,那么foreach还会显示吗?实际情况是不会输出,当然我们也可以设置输出,比如下面的代码,即使我们点了删除但是还是会显示:

 1 <ul> 2     <!--ko foreach:{data:people,as : ‘P‘,includeDestroyed:false} --> 3     <li> 4         <span data-bind="text: P.Name"></span> 5         <a href="" data-bind="click: $parent.destroy">删除</a> 6     </li> 7     <!--/ko --> 8 </ul> 9 10 11 <script type="text/javascript">12 13     var appViewModel = function () {14         var self = this;15         this.people = ko.observableArray([16             { Name: "aaaa" },17             { Name: "bbbb" },18             { Name: "cccc" },19             { Name: "dddd" }20         ]);21         this.destroy = function () {22             self.people.destroy(this);23         }24     }25 26     ko.applyBindings(new appViewModel());27 </script>

 

 

最后还要讲的就是回调,比如添加或者删除其实都是有对应的事件的,分别是afterRender,afterAdd,beforeRemove,beforeMode,afterMove。除了第一个事件以外,其他的事件都会有三个参数,分别是触发事件的项,项在数据在数组中的索引和数组本身。第一个事件接收的参数则是一组将要被插入的dom元素和对应被被绑定的数据项。

 

“if”绑定

有时我们需要控制页面标签的是否呈现,但是通过visible必须只能进行简单的控制,所以我们需要一个专门用来进行判断的绑定器,那就是if了,比如下面的示例,将通过一个Count监控属性控制元素是否呈现:

 1     <!--ko if:count --> 2     <div> 3         <h1>终于见面了</h1> 4     </div> 5     <!--/ko --> 6 <div> 7     <button type="button" data-bind="click:add">增加</button> 8     <button type="button" data-bind="click:subtract">减少</button> 9 </div>10 11 12 <script type="text/javascript">13 14     var appViewModel = function () {15         this.count = ko.observable(0);16         this.add = function () {17             this.count(this.count() + 1);18             console.log(this.count());19         };20         this.subtract = function () {21             this.count(this.count()-1);22         };23     }24 25     ko.applyBindings(new appViewModel());26 </script>

 

 

“ifnot”绑定

笔者就不单独介绍了,就是if反义。

 

“with”绑定

学习一定javascript一定知道with可以用来延长作用域,当然在KO中也基本类似。可以用来选定上下文环境,当然靠说还是没用,具体可以看一段代码:

 1     <!--ko with:myArray --> 2     <div> 3         <h1>终于见面了<!--ko text:name --><!--/ko--></h1> 4     </div> 5     <!--/ko --> 6  7  8 <script type="text/javascript"> 9 10     var appViewModel = function () {11         this.myArray = { name: "1", text: "123" };12     }13 14     ko.applyBindings(new appViewModel());15 </script>

 

 

通过代码就比较好里面了,用了with之后知道结束标签,这中间的上下文环境都是with后面指定的对象,比如上面的代码中直接用text绑定了name,而不是myArray.name。在某些场合下能减少不必要的输入。