jquery radio设置checked但按钮radio仍然没选中的js处理方式-javascript bootstrap

来源:互联网 发布:数据分析平台需求文档 编辑:程序博客网 时间:2024/06/05 14:30

今天在用jQuery设置表单radio的选中时遇到了radio 设置checked但按钮还是没选中的情况:

<div class="form-group">  <label for="leader">是否有父机构?</label>  <form:radiobutton path="hasFather"  value="true" data-toggle="collapse" data-target="#edit_parent_div" />是  <form:radiobutton path="hasFather"  value="false" data-toggle="collapse" data-target="#edit_parent_div" />否</div>
第一次按radio切换没问题,但是当我第二次切换radio就出现两个radio都没选中的样子。(单选框只能选一个)

  if (object.hasFather) {        $("#editModal input[type='radio']").attr("checked", "true");     //   $("#editModal input[name='hasFather'][value='true']").attr("checked", "checked");      //  $("#editModal input[name='hasFather'][value=false]").attr("checked", false);        $("#editModal #edit_parent_div").collapse('show');      }else{        $("#editModal input[type='radio']").attr("checked", "false");      //  $("#editModal input[name='hasFather'][value='false']").select();      //  $("#editModal input[name='hasFather'][value=false]").attr("checked", true);        $("#editModal #edit_parent_div").collapse('hide');      }
如代码和注释一样,尝试了各种方法都有问题。查看网页源代码会发现两个radio都属于checked状态  checked="checked"。

遇到这种问题的原因在于attr()方法使用不当。

应该使用prop()设置DOM节点属性。

$("#editModal input[name='hasFather'][value='true']").prop("checked", "checked");
这样页面就正常了。

原因:

  • attr方法主要处理自定义的DOM属性。
  • prop方法主要处理本身就带有的固有属性。
例如这里的checked是radio的自带的属性,所以这里应该使用prop()。
W3C标准里说明的属性,或者说在IDE里能够智能提示出的属性,这些都是固有属性。

而我们为html元素自定义(本身没有的)的属性则用attr()。

如果使用prop方法处理固定属性的取值和设置属性值时,都会返回undefined值。


jQuery 中 attr() 和 prop() 方法的区别

那么,什么时候使用attr(),什么时候使用prop()?

To retrieve and change DOM properties such as the checked, selected, or disabled state of form elements, use the .prop() method. 

根据官方的建议:具有 true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),其他的使用 attr()

到此,将 attr('checked') 改成 prop('checked') 即可修复提的 issues 了。

^_^

等等,貌似问题还没真正解决,为什么开头例子中 jQuery 1.8.3 和 1.9.0 使用 attr() 会有所区别呢?

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

1.8.3 attr():

attr: function( elem, name, value, pass ) {    var ret, hooks, notxml,        nType = elem.nodeType;    // don't get/set attributes on text, comment and attribute nodes    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {        return;    }    if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {        return jQuery( elem )[ name ]( value );    }    // Fallback to prop when attributes are not supported    if ( typeof elem.getAttribute === "undefined" ) {        return jQuery.prop( elem, name, value );    }    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );    // All attributes are lowercase    // Grab necessary hook if one is defined    if ( notxml ) {        name = name.toLowerCase();        hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );    }    if ( value !== undefined ) {        if ( value === null ) {            jQuery.removeAttr( elem, name );            return;        } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {            return ret;        } else {            elem.setAttribute( name, value + "" );            return value;        }    } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {        return ret;    } else {        ret = elem.getAttribute( name );        // Non-existent attributes return null, we normalize to undefined        return ret === null ?            undefined :            ret;    }}

1.9.0 attr():

    attr: function( elem, name, value ) {    var ret, hooks, notxml,        nType = elem.nodeType;    // don't get/set attributes on text, comment and attribute nodes    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {        return;    }    // Fallback to prop when attributes are not supported    if ( typeof elem.getAttribute === "undefined" ) {        return jQuery.prop( elem, name, value );    }    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );    // All attributes are lowercase    // Grab necessary hook if one is defined    if ( notxml ) {        name = name.toLowerCase();        hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );    }    if ( value !== undefined ) {        if ( value === null ) {            jQuery.removeAttr( elem, name );        } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {            return ret;        } else {            elem.setAttribute( name, value + "" );            return value;        }    } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {        return ret;    } else {        // In IE9+, Flash objects don't have .getAttribute (#12945)        // Support: IE9+        if ( typeof elem.getAttribute !== "undefined" ) {            ret =  elem.getAttribute( name );        }        // Non-existent attributes return null, we normalize to undefined        return ret == null ?            undefined :            ret;    }}

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

prop: function( elem, name, value ) {    var ret, hooks, notxml,        nType = elem.nodeType;    // don't get/set properties on text, comment and attribute nodes    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {        return;    }    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );    if ( notxml ) {        // Fix name and attach hooks        name = jQuery.propFix[ name ] || name;        hooks = jQuery.propHooks[ name ];    }    if ( value !== undefined ) {        if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {            return ret;        } else {            return ( elem[ name ] = value );        }    } else {        if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {            return ret;        } else {            return elem[ name ];        }    }}

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

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

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

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

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

return ( elem[ name ] = value );return elem[ name ];

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

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

hooks.get( elem, name )) 

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

1.8.3 中

boolHook = {    get: function( elem, name ) {        // Align boolean attributes with corresponding properties        // Fall back to attribute presence where some booleans are not supported        var attrNode,            property = jQuery.prop( elem, name );        return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?            name.toLowerCase() :            undefined;    }}

1.9.0 中

boolHook = {    get: function( elem, name ) {        var            // Use .prop to determine if this attribute is understood as boolean            prop = jQuery.prop( elem, name ),            // Fetch it accordingly            attr = typeof prop === "boolean" && elem.getAttribute( name ),            detail = typeof prop === "boolean" ?                getSetInput && getSetAttribute ?                    attr != null :                    // oldIE fabricates an empty string for missing boolean attributes                    // and conflates checked/selected into attroperties                    ruseDefault.test( name ) ?                        elem[ jQuery.camelCase( "default-" + name ) ] :                        !!attr :                // fetch an attribute node for properties not recognized as boolean                elem.getAttributeNode( name );        return detail && detail.value !== false ?            name.toLowerCase() :            undefined;    }}

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

那么我们的结论是:

具有 true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),其他的使用 attr(),具体见下表:







2 0