就是类似于QQ空间上传图片的那种效果,在一堆东西中随意选择,选中的项不仅有标识,还有标识一个数字,表示是第几个被你选中的。点击未选中的东西,会被认为是最新选中的,而点击已选中的东西,会被认为是取消选择,其他的东西将重新显示他们的排序。
这个效果是之前做一个项目的时候需要的,用户需要选择他们想要的东西,而且这些东西是有序的。这个效果是后端的同事做的,我只是做了个静态页面的展示,设计的右上角的红点和红点的字的样式而已,当时感觉脑子一团浆糊,没有做这个的思路,但是后来不甘心,于是就尝试自己做了一个。
本人不才,这个demo花了两个晚上的时间才大功告成,在网上暂时没有发现类似demo的示例,所以在这里分享一下。代码如下:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <script type="text/javascript" src="js/jquery-1.11.0.js" ></script> 7 <link rel="stylesheet" href="css/Allstyle.css" /> 8 <style> 9 .g-li{ 10 position: relative; 11 width: 150px; 12 height: 100px; 13 margin: 10px; 14 border:1px solid #dedede; 15 } 16 .g-li .c{ 17 content: ""; 18 position: absolute; 19 top:-10px; 20 right: -10px; 21 width: 20px; 22 height: 20px; 23 color: #fff; 24 font-size: 12px; 25 text-align: center; 26 line-height: 20px; 27 display: none; 28 border-radius: 10px; 29 background-color: red; 30 } 31 .g-li.active .c{ 32 display: block; 33 } 34 </style> 35 </head> 36 <body> 37 <ul class="flex"> 38 <li class="g-li">第一个 39 <div class="c"></div> 40 </li> 41 <li class="g-li ">第二个 42 <div class="c"></div> 43 </li> 44 <li class="g-li">第三个 45 <div class="c"></div> 46 </li> 47 <li class="g-li">第四个 48 <div class="c"></div> 49 </li> 50 <li class="g-li">第五个 51 <div class="c"></div> 52 </li> 53 <li class="g-li">第六个 54 <div class="c"></div> 55 </li> 56 </ul> 57 <script> 58 $(function(){ 59 var arr=new Array();//有红点的元素的集合 60 //1.点击li给它加上红点或去掉红点 61 //2.如果是加上红点就往红点数组追加一个元素,如果去掉红点就在数组中找到这个值并去除 62 //3.每次点击完,处理好红点数组之后,遍历新的数组,重新给点赋值 63 $('.g-li').on('click',function(){ 64 if($(this).hasClass('active')){ 65 $(this).removeClass('active'); 66 //注意,这里找到要去掉的值是多少以后,就直接在数组删去,这个环节不需要循环 67 var idx=$(this).index(); 68 var i = $.inArray(idx,arr); 69 arr.splice(i,1); 70 71 } 72 else{ 73 $(this).addClass('active'); 74 //追加到最后 75 arr.push($(this).index()); 76 } 77 //注意,重复定义变量在js中不报错,可是该变量会在第二次初始化语句执行前都是undefined 78 //注意,每次点击都会影响到红点数组元素,所以每次点击完再写字 79 var num=1;//写字的时候从1开始标号 80 for(var a=0;a<arr.length;a++){ 81 //注意,arr里保存的是数字,都是红点元素的下标值,要先根据下标找到节点才可以 82 //注意,arr不是对象节点,不要用each来遍历 83 var index=arr[a]; 84 $(".g-li").eq(index).find('.c').html(num++); 85 } 86 console.log(arr); 87 88 }) 89 90 }) 91 92 </script> 93 </body> 94 </html>
简单介绍一下我写的这个代码:准备了一个ul,里头的li是候选项的集合,(这里使用了flex布局,一行摆放多个li,看起来效果更直观)每一个li都有一个带有一个叫‘c’的class的div,默认这个div是不显示的,li选中时,li的右上角会出现红点,红点中的数字表示这是你第几个选中的东西 。用jq进行处理点击li的事件,包括li的“.c”的div是否出现,数字的输出。
在这里来分享几个遇到的坑,就是注释里标注了“注意”的地方:敲错了单词和名称的错误就不说了;不小心定义了两次arr,结果报错arr是undefined也不说了;
最近才知道jq有一个核心方法叫$.inArray(),这个方法的效果类似于字符串的indexOf方法(可以查到某字符是某字符串的第几个字符,找到返回下标,找不到返回-1),这个方法是查找某值是某数组中的第几个元素,找到返回下标,找不到返回-1,考虑到这里选择的项目顺序是随意的,下标必须要记录,所以选择了数组记录。点击到已选项目的时候会去查找这是数组里的第几个元素,就用了这个方法,结果运行到后面出了意外,在断点调试的时候发现并没有成功删除元素,因为这个方法的参数弄反了。$.inArray()的参数有两个,第一个是要判断的值, 第二个是要判断的数组;
jq的另一个操作数组的核心方法$.each(),可以说是非常神通广大了,可以遍历数组,也可以遍历类数组对象,也可以遍历对象属性。于是这里我就用这个来遍历表示已选项顺序的数组了,结果并不是我需要的。断点调试了以后,感觉是$.each()这里的问题,于是我把这里的遍历改成了for循环,遍历就正常了;
对于这个demo的思路,我很容易想太复杂,我曾经以为选中的项数组应该是一个json数组,一个是记录它被点击的顺序,一个是记录了它自己的下标,点击到已选元素的时候,要挨个判断已选项数组,如果被点击的顺序小于该项则不做处理,否则都减去1,结果越想越复杂;我还以为删除数组元素的时候要循环判断哪个元素的值与要去掉的值相同,再删去它;我甚至以为被选中的数组应该是li节点的集合……
最后我去看了一个选择某些项目并删除的demo的代码,这才恍然大悟,它的思路是新选择一个,就记录它的下标到数组中,取消选择一个,就从数组中删去这个项的下标,最后根据下标来找到实际的节点。
所以思路其实很简单:点击li的时候,如果是红点没有出现的li,就给它加上红点,然后追加它的下标到数组中,如果是已有红点的li,首先去掉红点,然后获取它的下标,在数组中找到这个值并删除,这样,已选项数组就操作完毕了;然后根据数组中的值,找到实际的li节点,给红点输出数字即可,输出数字之前,给一个全局变量赋值为1,遍历已选项数组,一边输出这个全局变量一边自增全局变量即可,因为已选项数组的元素已经根据点击的先后排好顺序了,所以这个时候输出的结果肯定是正确的。
最后上效果图:
再次点击第二个li,效果如下: