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

今天在用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");  

这样页面就正常了。
原因:
1. attr方法主要处理自定义的DOM属性。
2. 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(),具体见下表:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/hongc93/article/details/75308654