全选功能就是
1.点击全选控制循环元素是否选中。(点击全选,下面的所有元素选中,再次点击 所有元素取消选中。)
2.点击循环元素控制全选。(如果当前元素是未选中状态则全选不选中,如果当前元素是选中状态并且检查其他也是选中状态则全选按钮也选中,如果当前元素是选中状态并且检查其他的不全都是全中状态则全选按钮不选中)
首先我们来建一个avalon页面。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>select all</title> 6 <script type="text/javascript" src="../avalon.shim.js" ></script> 7 <script type="text/javascript"> 8 var model=avalon.define({ 9 $id:"test", 10 data:[{checked:false},{checked:false},{checked:false}] 11 }); 12 </script> 13 </head> 14 <body> 15 <table ms-controller="test" border="1"> 16 <tr> 17 <td><input type="checkbox" />全选</td> 18 </tr> 19 <tr ms-repeat="data">//ms-repeat="data"放入需要循环的元素中(这里需要循环tr,data是vm里头定义的属性,属性值类型是对象数组,对象是checked:false未被选中的意思) 20 <td><input type="checkbox" />xxxxxxx</td> 21 </tr> 22 </table> 23 </body> 24 </html>
效果是这样的:
实现全选效果功能点一:
1.在全选input上加上双向绑定属性ms-duplex-checked="allchecked"
2.在vm里头定义属性allchecked:false(跟第一步的双向绑定值对应,如果是false就是不选中,如果是true就是选中)
3.在全选input上再加上data-duplex-changed="checkAll",这个事件绑定属性的意思是当全选的checkbox状态发生变化时触发。
4.定义checkAll函数。函数里头需要将当前的全选的checkbox的值赋给vm的allchecked属性这样这个属性的值就随着checkbox的值的变化而变化。然后把这个值赋给一个变量,方便后边用。然后我们遍历vm的data,通过形参el获取到每个checkbox对象,然后把上边定义的变量赋给每个checkbox对象。这样我们三个checkbox的值就跟全选的checkbox的值保持一致了。
5.在循环元素中添加ms-duplex-checked="el.checked",双向同步checkbox属性,将全选的属性赋给每个循环元素。
好了,到这一步,功能点一就实现了。点击全选 下面的所有元素选中,再次点击 所有元素取消选中。
我们看下代码和效果:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>select all</title> 6 <script type="text/javascript" src="../avalon.shim.js" ></script> 7 <script type="text/javascript"> 8 var model=avalon.define({ 9 $id:"test", 10 data:[{checked:false},{checked:false},{checked:false}], 11 allchecked:false, 12 checkAll:function(){ 13 var bool = model.allchecked = this.checked; 14 model.data.forEach(function(el){ 15 el.checked = bool; 16 }); 17 } 18 }); 19 </script> 20 </head> 21 <body> 22 <table ms-controller="test" border="1"> 23 <tr> 24 <td><input type="checkbox" ms-duplex-checked="allchecked" data-duplex-changed="checkAll"/>全选</td> 25 </tr> 26 <tr ms-repeat="data"> 27 <td><input type="checkbox" ms-duplex-checked="el.checked"/>xxxxxxx</td> 28 </tr> 29 </table> 30 </body> 31 </html>
实现全选效果功能点二:
分析:要实现下面三个checkbox点击控制全选checkbox,就要在下面对象元素中添加对象监听方法,这样在每点一次都执行一次方法判断对全选checkbox的操作。
1.在循环对象元素中添加对象监听属性data-duplex-changed="checkOne"
2.在vm里写checkOne函数方法(也就是没点击一次循环元素要执行的方法)。这个方法是实现功能点二的关键。逻辑我们来分析一下。首先我们要判断当前的元素是否是选中,如果没有选中,就将vm里头的allchecked赋为false,这样全选也就同步为不选中了;如果选中,就调用vm里面data这个数组的一个every方法,这个方法用来检查data数组中的每个元素值是否相同,只要有一个不符合就返回false,否则返回true,这个逻辑恰恰就是我们要的逻辑。好,有这个返回值之后我们就可以把这个赋给vm里头的allchecked,这样就实现了如果是选中并且每个元素都选中的时候就返回true赋给全选的checkbox这样全选也选中了。如果是选中但是检查下来不是每个元素都一致那么就返回false,这个时候全选的checkbox还是未选中状态。
好,到这里我们就实现了功能点二了。看下代码和视图。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>select all</title> 6 <script type="text/javascript" src="../avalon.shim.js" ></script> 7 <script type="text/javascript"> 8 var model=avalon.define({ 9 $id:"test", 10 data:[{checked:false},{checked:false},{checked:false}], 11 allchecked:false, 12 checkAll:function(){ 13 var bool = model.allchecked = this.checked; 14 model.data.forEach(function(el){ 15 el.checked = bool; 16 }); 17 }, 18 checkOne:function(){ 19 if(!this.checked){ 20 model.allchecked = false; 21 }else{ 22 model.allchecked = model.data.every(function(el){ 23 return el.checked; 24 }); 25 } 26 } 27 }); 28 </script> 29 </head> 30 <body> 31 <table ms-controller="test" border="1"> 32 <tr> 33 <td><input type="checkbox" ms-duplex-checked="allchecked" data-duplex-changed="checkAll"/>全选</td> 34 </tr> 35 <tr ms-repeat="data"> 36 <td><input type="checkbox" ms-duplex-checked="el.checked" data-duplex-changed="checkOne"/>xxxxxxx</td> 37 </tr> 38 </table> 39 </body> 40 </html>
总结分析:
全选效果其实就是两步:
第一步是点全选控制下面的循环元素是否选中。
第二步是点循环元素控制全选元素是否选中。(这一步是关键,因为循环元素有多个所以在判断当前元素选中的时候还得判断其他元素是否保持一致,如果保持一致就选中,没保持一致就不选中)
然后第一步要vm定义一个布尔属性用于同步全选的状态,还要定义一个监听函数用于将当前的状态赋给下面循环元素的状态。
难点总结:
功能点一上:forEach方法用于遍历data,通过形参el获取到每个checkbox对象,el.checked=bool的意思是将每个checkbox对象的值都赋上全选checkbox的值。这样三个checkbox的值就跟全选的checkbox的值同步了。
功能点二上:点击循环元素控制全选跟点击全选控制循环元素的不同在于循环元素的条数是有可能会大于1的,所以这个时候就要增加一个对每个循环元素值是否一致的判断。every方法是data数组的。能检查data数组下每个元素的值是否相同,相同则返回true,不相同返回false。