复选框的一些事儿
原文地址:复选框的一些事儿
对复选框总觉得云里雾里,判断选中与未选中的方法总觉得不明白,调整复选框与文字的对齐怎么调都没用,以前总没有动力去花一个真正的时间去解决这些问题,受到今天项目的启发,所以来弄清楚一下。
1、先来说说选中与未选中的方法与判断问题
在表单中,
1 <form action=""> 2 3 <input type="checkbox" id="test">复选框 4 5 </form> 6 7 <script> 8 $(function(){ 9 10 var test = $('#test').val(); 11 console.log(test); //on 12 13 }); 14 </script>
不管你选没选中,复选框的val都是on,所以肯定是不能用这个来判断的。
在原生的js中,我们可以用对象的checked属性,如下:
var test = document.getElementById('test').checked; console.log(test); //false
比如我们用来点击事件发生时判断:
1 <form action=""> 2 3 <input type="checkbox" id="test" onclick="check(this)">复选框 4 5 </form> 6 7 <script> 8 9 function check(obj){ 10 console.log(obj.checked); 11 } 12 </script>
你会发现你可以自由的判断是否选中了
但很多情况下我们都是结合jquery来使用的,在jquery中,很多人都是使用的$().addAttr('checked', 'checked'); 给这个复选框的DOM添加checked属性,其实这个并没有真正的选中复选框,来看个例子:
1 <form action=""> 2 3 <input type="checkbox" id="test2" checked onclick="check(this)">复选框2 4 5 </form> 6 7 <script> 8 function check(obj){ 9 console.log(obj.checked); 10 } 11 </script>
此时你会发现
这里是我们添加的checked属性,添加了这个属性,默认是选中的,也就是说,添加了checked属性后js对象的checked属性默认是选中的,我们打印下:
var test = document.getElementById('test2').checked; console.log(test); //true
但是我们点击复选框去掉选中的时候,DOM结构中的checked属性是不会被去掉的,但此时js对象的checked实际上是等于false的。也就是说这并不是一个可逆的过程,需要我们手动移除attr为checked的属性。
但比如下种情况的时候
1 <ul> 2 <li style="background:#eee;"> 3 <input type="checkbox" id="test3"> 复选框3 4 </li> 5 </ul>
我想要实现的是点击li元素的文字就可以实现选中状态,当然点击复选框本身也可以实现选中状态,那么应该怎么做呢?
当然首先想到的肯定是:
1 <ul> 2 <li style="background:#eee;" onclick="check3()"> 3 <input type="checkbox" id="test3"> 复选框3 4 </li> 5 </ul> 6 7 <script> 8 $(function(){ 9 10 var test3 = document.getElementById('test3'); 11 function check3(){ 12 if(test3.checked) 13 test3.checked = false; 14 else 15 test3.checked = true; 16 } 17 18 </script>
此时,你会发现点击li元素的确可以实现选中,但是,点击复选框本身就没有任何反应了,这是为什么?为什么?为什么呢?
想想就知道是事件冒泡的问题了,复选框本身在li元素中,li元素本身也会有点击事件,当你点击复选框时,它其实是执行了的,但后来又执行了一次li元素的点击事件,导致复选框看起来没变化。
在这里我们可以阻止默认事件的发生,打印结果:
var test3 = document.getElementById('test3'); function check3(){ if(test3.checked) test3.checked = false; else test3.checked = true; } $('#test3').click(function(event){ console.log(this.checked); event.stopPropagation(); });
在这里就要说说阻止默认事件和行为的3种方法的区别:(此处粘贴)
1.event.stopPropagation();
事件处理过程中,阻止了事件冒泡,但不会阻击默认行为(它就执行了超链接的跳转)
2.return false;
事件处理过程中,阻止了事件冒泡,也阻止了默认行为(比如刚才它就没有执行超链接的跳转)
3.event.preventDefault();
如果把它放在头部A标签的click事件中,点击“点击我”。
会发现它依次弹出:我是最里层---->我是中间层---->我是最外层,但最后却没有跳转到百度
它的作用是:事件处理过程中,不阻击事件冒泡,但阻击默认行为(它只执行所有弹框,却没有执行超链接跳转)
这里就要来说说jquery的prop()和attr()的区别,其实前面也提到过,this.checked 和 $(this).attr('checked')的区别,this指的是js对象,而$(this)指的是DOM对象,他们拥有的属性都是不一样的,比如
<a id="a" href="ymblog.net"></a>
$(this).attr()属性就包含了id和href,而不包含style.width或者style.color,因为这些在js对象的style属性里面,
$('#a').click(function(){ console.log(this.id); //a console.log(this.href); //ymblog.net console.log($(this).style); //undefined });
说明this对象中包含了DOM对象的属性,反之则不是。
在这里的prop和attr也是一样的,区别就好比this.checked与$(this).attr('checked');一样。
详细可以参考这篇文章:jQuery中attr和prop方法的区别
了解完这2个属性以后,让我们再来回顾前面的li元素中包裹的复选框的情况,在这里这样使用呢?
如下:
1 <ul> 2 <li style="background:#eee;" id="test4"> 3 <input type="checkbox" > 复选框4 4 </li> 5 </ul> 6 <a href="#" id="aaa">移除</a> 7 8 <script> 9 10 $('#test4').click(function(){ 11 $(this).find('input').attr('checked', 'checked'); 12 }) 13 $('#aaa').click(function(){ 14 $('#test4').find('input').removeAttr('checked'); 15 }); 16 </script>
如果你去运行,试过之后就会发现,第一次点击li元素,它会勾选,然后点击移除它会去掉勾选,这似乎很正常啊,但当你第二次点击以后,它不勾选了,没反应了了,为什么呢?
我们可以来打印第一次点击以后的this.checked
$('#test4').click(function(){ $(this).find('input').attr('checked', 'checked'); console.log(document.getElementById('test5').checked); }) $('#aaa').click(function(){ $('#test4').find('input').removeAttr('checked'); console.log(document.getElementById('test5').checked); });
我们每次都打印一下,下面是运行结果:
你会看到第一次点击以后,为input添加checked属性,this.checked = true;点击移除checked属性以后,this.checked = false;但是当第二次点击为input添加checked属性时,input却没有被勾选,也就是没有被checked。这是为什么?谁能告诉我?为什么?(待解决~)
在这里如果再用prop()checked一次,又会正常了,这也证明了前面的正确性
$('#test4').click(function(){ $(this).find('input').attr('checked', 'checked'); $(this).find('input').prop('checked', true); }) $('#aaa').click(function(){ $('#test4').find('input').removeAttr('checked'); $('#test4').find('input').prop('checked', false); });
在这里觉得移除prop('checked',false);可以去掉,为什么呢?
$('#test4').click(function(){ $(this).find('input').attr('checked', 'checked'); $(this).find('input').prop('checked', true); console.log(document.getElementById('test5').checked); }) $('#aaa').click(function(){ $('#test4').find('input').removeAttr('checked'); // $('#test4').find('input').prop('checked', false); console.log(document.getElementById('test5').checked); });
你会发现,不起作用的只有第二次点击选中的时候attr('checked', 'checked');而removeAttr('checked');每次都起到了checked = false;的作用。
在这里我似乎不能完全理解明白,有弄清楚的大神麻烦私信一份给我谢谢(472102644@qq.com)!
但我们在这里的解决办法还是有的,
比如上面的input复选框被包裹在一层li元素的情况下,你在为input添加checked属性以后,再为它的this对象的checked属性赋值为true,这样就确保了input真正的选中。
出现问题的根本原因在于,你为input复选框(第一次是有效果的)添加checked属性以后,它并不会被checked,也就是说$(this).find('input')[0].checked == false;始终等于false。
也就是这段代码,感兴趣的可以去试试
1 <ul> 2 <li style="background:#eee;" id="test6"> 3 <input type="checkbox" id="input"> 复选框5 4 </li> 5 </ul> 6 7 <script> 8 $('#test6').click(function(){ 9 if( $(this).find('input').attr('checked') == 'checked'){ 10 $(this).find('input').removeAttr('checked'); 11 console.log($(this).find('input')[0].checked) 12 } 13 else{ 14 $(this).find('input').attr('checked',"checked"); 15 console.log($(this).find('input')[0].checked) 16 } 17 18 </script>
有人说,那你用prop判断不久可以了,你用prop后,点击input事件就会冒泡了,又回到了前面说的问题。
关于样式的深入理解下一篇再学习研究,这里就先到这儿了。
参考文章: