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

今天在用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(),具体见下表:







评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值