A-A+

jquery attr方法获取input的checked属性问题

2016年01月12日 web前端设计 暂无评论 阅读 6 views 次

本文章来为各位介绍一篇关于jquery attr方法获取input的checked属性问题总结,希望本文章能够帮助到各位朋友。

问题:经常使用jQuery插件的attr方法获取checked属性值,获取的值的大小为未定义,此时可以用prop方法获取其真实值,下面介绍这两种方法的区别:

1.通过prop方法获取checked属性,获取的checked返回值为boolean,选中为true,否则为flase

  1. <input type="<a href="/tags.php/checkbox/" target="_blank">checkbox</a>id="<a href="/tags.php/select/" target="_blank">select</a>All" onclick="checkAll()">全选   
  2. function checkAll()   
  3. {   
  4. var checkedOfAll=$("#selectAll").prop("checked");   
  5. alert(checkedOfAll);   
  6. $("input[name='procheck']").prop("checked", checkedOfAll);   
  7. }  

2.如果使用attr方法获取时,如果当前input中初始化未定义checked属性,则不管当前是否选中,

  1. $("#selectAll").attr("checked")都会返回<a href="/tags.php/undefined/" target="_blank">undefined</a>;  
  2.    
  3. <input type="checkbox" id="selectAll" onclick="checkAll()" >全选  

如果当前input中初始化已定义checked属性,则不管是否选中,$("#selectAll").attr("checked")都会返回checked.

  1. <input type="checkbox" id="selectAll" onclick="checkAll()" checked>全选   
  2. function checkAll()   
  3. {   
  4. var checkedOfAll=$("#selectAll").attr("checked");   
  5. alert(checkedOfAll);   
  6. $("input[name='procheck']").attr("checked", checkedOfAll);   
  7. }  

于是,开始调试代码,在 1.9.0 的版本中:

  1. <input type="checkbox" />  
  2.    
  3. <script>  
  4.    
  5. $(function() {  
  6.    
  7. $('input').click(function() {  
  8.    
  9. $(this).attr('checked');  
  10.    
  11. });  
  12.    
  13. });  
  14.    
  15. </script>  

点击 checkbox,结果都是 undefined,而在 1.8.3 的版本中,结果是 checked 和 undefined,到这里,问题答案找到了,就是使用 attr() 方法的问题,于是查看官方文档, 才知道从 jQuery 1.6 开始新增了一个方法 prop(),但是一直都没有使用过。

从中文意思看,两者分别是获取/设置 attributes 和 properties 的方法,那么为什么还要增加 prop() 方法呢?

因为在 jQuery 1.6 之前,使用 attr() 有时候会出现不一致的行为,那么,什么时候使用attr(),什么时候使用prop()?根据官方的建议:具有 true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),其他的使用 attr(),到此,将 attr(‘checked’) 改成 prop(‘checked’) 即可修复提的 issues 了。等等,貌似问题还没真正解决,为什么开头例子中 jQuery 1.8.3 和 1.9.0 使用 attr() 会有所区别呢?

想知道他们的区别,最好的办法还是看他们的源代码:

1.8.3 attr():

  1. attr: function( elem, name, value, pass ) {  
  2.    
  3. var ret, hooks, notxml,  
  4.    
  5. nType = elem.nodeType;  
  6.    
  7. // don't get/set attributes on text, comment and attribute nodes  
  8.    
  9. if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {  
  10.    
  11. return;  
  12.    
  13. }  
  14.    
  15. if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {  
  16.    
  17. return jQuery( elem )[ name ]( value );  
  18.    
  19. }  
  20.    
  21. // Fallback to prop when attributes are not supported  
  22.    
  23. if ( typeof elem.getAttribute === "undefined" ) {  
  24.    
  25. return jQuery.prop( elem, name, value );  
  26.    
  27. }  
  28.    
  29. notxml = nType !== 1 || !jQuery.isXMLDoc( elem );  
  30.    
  31. // All attributes are lowercase  
  32.    
  33. // Grab necessary hook if one is defined  
  34.    
  35. if ( notxml ) {  
  36.    
  37. name = name.toLowerCase();  
  38.    
  39. hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );  
  40.    
  41. }  
  42.    
  43. if ( value !== undefined ) {  
  44.    
  45. if ( value === null ) {  
  46.    
  47. jQuery.removeAttr( elem, name );  
  48.    
  49. return;  
  50.    
  51. else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {  
  52.    
  53. return ret;  
  54.    
  55. else {  
  56.    
  57. elem.setAttribute( name, value + "" );  
  58.    
  59. return value;  
  60.    
  61. }  
  62.    
  63. else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {  
  64.    
  65. return ret;  
  66.    
  67. else {  
  68.    
  69. ret = elem.getAttribute( name );  
  70.    
  71. // Non-existent attributes return null, we normalize to undefined  
  72.    
  73. return ret === null ?  
  74.    
  75. undefined :  
  76.    
  77. ret;  
  78.    
  79. }  
  80.    
  81. }  

1.9.0 attr():

  1. attr: function( elem, name, value ) {  
  2.    
  3. var ret, hooks, notxml,  
  4.    
  5. nType = elem.nodeType;  
  6.    
  7. // don't get/set attributes on text, comment and attribute nodes  
  8.    
  9. if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {  
  10.    
  11. return;  
  12.    
  13. }  
  14.    
  15. // Fallback to prop when attributes are not supported  
  16.    
  17. if ( typeof elem.getAttribute === "undefined" ) {  
  18.    
  19. return jQuery.prop( elem, name, value );  
  20.    
  21. }  
  22.    
  23. notxml = nType !== 1 || !jQuery.isXMLDoc( elem );  
  24.    
  25. // All attributes are lowercase  
  26.    
  27. // Grab necessary hook if one is defined  
  28.    
  29. if ( notxml ) {  
  30.    
  31. name = name.toLowerCase();  
  32.    
  33. hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );  
  34.    
  35. }  
  36.    
  37. if ( value !== undefined ) {  
  38.    
  39. if ( value === null ) {  
  40.    
  41. jQuery.removeAttr( elem, name );  
  42.    
  43. else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {  
  44.    
  45. return ret;  
  46.    
  47. else {  
  48.    
  49. elem.setAttribute( name, value + "" );  
  50.    
  51. return value;  
  52.    
  53. }  
  54.    
  55. else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {  
  56.    
  57. return ret;  
  58.    
  59. else {  
  60.    
  61. // In IE9+, Flash objects don't have .getAttribute (#12945)  
  62.    
  63. // Support: IE9+  
  64.    
  65. if ( typeof elem.getAttribute !== "undefined" ) {  
  66.    
  67. ret = elem.getAttribute( name );  
  68.    
  69. }  
  70.    
  71. // Non-existent attributes return null, we normalize to undefined  
  72.    
  73. return ret == null ?  
  74.    
  75. undefined :  
  76.    
  77. ret;  
  78.    
  79. }  
  80.    
  81. }  

1.8.3 和 1.9.0 的 prop() 是一样的:

  1. prop: function( elem, name, value ) {  
  2.    
  3. var ret, hooks, notxml,  
  4.    
  5. nType = elem.nodeType;  
  6.    
  7. // don't get/set properties on text, comment and attribute nodes  
  8.    
  9. if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {  
  10.    
  11. return;  
  12.    
  13. }  
  14.    
  15. notxml = nType !== 1 || !jQuery.isXMLDoc( elem );  
  16.    
  17. if ( notxml ) {  
  18.    
  19. // Fix name and attach hooks  
  20.    
  21. name = jQuery.propFix[ name ] || name;  
  22.    
  23. hooks = jQuery.propHooks[ name ];  
  24.    
  25. }  
  26.    
  27. if ( value !== undefined ) {  
  28.    
  29. if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {  
  30.    
  31. return ret;  
  32.    
  33. else {  
  34.    
  35. return ( elem[ name ] = value );  
  36.    
  37. }  
  38.    
  39. else {  
  40.    
  41. if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {  
  42.    
  43. return ret;  
  44.    
  45. else {  
  46.    
  47. return elem[ name ];  
  48.    
  49. }  
  50.    
  51. }  
  52.    
  53. }  

首先,我们看下 attr() 和 prop() 的区别:

attr() 里面,最关键的两行代码

  1. elem.setAttribute( name, value + "" );  
  2.    
  3. ret = elem.getAttribute( name );  

很明显的看出来,使用的 DOM 的 API setAttribute() 和 getAttribute() 方法操作的属性元素节点。

prop() 里面,最关键的两行代码

  1. return ( elem[ name ] = value );  
  2.    
  3. return elem[ name ];  

可以理解为 document.getElementById(el)[name] = value,这是转化成 element 的一个属性。

对比调试 1.9.0 和 1.8.3 的 attr() 方法,发现两者的区别在于

hooks.get( elem, name ))

返回的值不一样,具体的实现:

1.8.3 中

  1. boolHook = {  
  2.    
  3. get: function( elem, name ) {  
  4.    
  5. // Align boolean attributes with corresponding properties  
  6.    
  7. // Fall back to attribute presence where some booleans are not supported  
  8.    
  9. var attrNode,  
  10.    
  11. property = jQuery.prop( elem, name );  
  12.    
  13. return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?  
  14.    
  15. name.toLowerCase() :  
  16.    
  17. undefined;  
  18.    
  19. }  
  20.    
  21. }  

1.9.0 中

  1. boolHook = {  
  2.    
  3. get: function( elem, name ) {  
  4.    
  5. var  
  6.    
  7. // Use .prop to determine if this attribute is understood as boolean  
  8.    
  9. prop = jQuery.prop( elem, name ),  
  10.    
  11. // Fetch it accordingly  
  12.    
  13. attr = typeof prop === "boolean" && elem.getAttribute( name ),  
  14.    
  15. detail = typeof prop === "boolean" ?  
  16.    
  17. getSetInput && getSetAttribute ?  
  18.    
  19. attr != null :  
  20.    
  21. // oldIE fabricates an empty string for missing boolean attributes  
  22.    
  23. // and conflates checked/selected into attroperties  
  24.    
  25. ruseDefault.test( name ) ?  
  26.    
  27. elem[ jQuery.camelCase( "default-" + name ) ] :  
  28.    
  29. !!attr :  
  30.    
  31. // fetch an attribute node for properties not recognized as boolean  
  32.    
  33. elem.getAttributeNode( name );  
  34.    
  35. return detail && detail.value !== false ?  
  36.    
  37. name.toLowerCase() :  
  38.    
  39. undefined;  
  40.    
  41. }  
  42.    
  43. }  

由此可见,1.9.0 开始不建议使用 attr() 来对具有 true 和 false 两个属性的属性进行操作了。

那么我们的结论是:具有 true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),其他的使用 attr()。

标签:

给我留言