jQuery中设置对象属性有以下几种:
1、获取属性attr(name)
$("img").attr("src");
2、设置属性attr(name,value)
$("img").attr("src","test.jpg");
3、批量设置属性attr(properties)
$("img").attr({ src: "test.jpg", alt: "Test Image" });
4、为所有匹配的元素设置一个计算的属性值,由这个函数计算的值作为属性值。 attr(key, function(index, attr))
$("img").attr("title", function() { return this.src });
// 获取当前元素的src值作为title属性值
5、移除属性 removeAttr(name)
$("img").removeAttr("src");
其中都会用到jQuery对象的attr方法,attr的源代码如下:
jQuery.fn.extend({
attr: function( name, value ) {
return access( this, name, value, true, jQuery.attr );
})
可以看到,attr只是起到一个传值的作用,然后返回的是access的返回值,再来看看access函数中的代码:
function access( elems, key, value, exec, fn, pass) {
var length = elems.length;
// 如果key是对象,则拆分成名值单独赋值
if ( typeof key === "object" ) {
for ( var k in key ) {
access( elems, k, key[k], exec, fn, value );
}
return elems;
}
// 如果value含值,则给属性赋值
if ( value !== undefined ) {
// 如果value为函数的时候综合判断是否需要执行此函数
// 判断VALUE是否为函数,是函数则exec为true
exec = !pass && exec && jQuery.isFunction(value);
// 拆分对象,单独赋值
for ( var i = 0; i < length; i++ ) {
// 对单独的对象调用jQuery.attr,设置属性
// 如果value是函数则执行value.call( elems[i], i, fn( elems[i], key ) )
fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass);
}
// 返回对象数组
return elems;
}
// 如果上面的条件都不符合,length有值则获取属性值,无对象则为undefined
return length ? fn( elems[0], key ) : undefined;
}
access就像它单词的意思一样是一个入口,判断key、value值的不同类型,最终会把值传递给jQuery的静态方法attr处理,即($.attr()):
attr静态方法中分别对浏览器的兼容性、各种特殊属性做了相应的处理
jQuery.extend({
attrFn: {
val: true,
css: true,
html: true,
text: true,
data: true,
width: true,
height: true,
offset: true
},
attr: function( elem, name, value, pass ) {
// don't set attributes on text and comment nodes
// 如果对象为空、文字、注释则返回undefined
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
return undefined;
}
// 如果 name为 val、css、html、text、data、width、height、offset
// 则直接调用jquery对应的方法如:$('p').html(value);
if ( pass && name in jQuery.attrFn ) {
return jQuery(elem)[name](value);
}
// 不是xml文档
var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
// Whether we are setting (or getting)
// 是否需要设置或者获取
set = value !== undefined;
// Try to normalize/fix the name
// 转换为适配的属性,如 class -> className
name = notxml && jQuery.props[ name ] || name;
// Only do all the following if this is a node (faster for style)
// 元素element 对象
if ( elem.nodeType === 1 ) {
// These attributes require special treatment
// rspecialurl = /href|src|style/
var special = rspecialurl.test( name );
// Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
/*
* 以下为opselected的bug修复
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<select id="optSelected">
</select>
<script type="text/javascript">
var select = document.getElementById('optSelected');
var option = document.createElement('option');
select.appendChild(option);
console.log(option.selected);
</script>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以下为各浏览器中运行结果:
浏览器 | 结果
----------- | -----
IE6 | false
IE7 | false
IE8 | false
IE9 beta | false
Firefox 3.6 | true
Chrome 7 | true
Safari 5 | false
经测试,IE系列和Safari使用`appendChild`对空的`<select>`元素添加一个`<option>`后,该`<option>`的`selected`属性不会被默认设置为**true**。
该问题引起的BUG描述如下:
> 部分浏览器在获取option的selected属性时,会错误地返回false。
该问题的解决方案是在访问`selected`属性时,先访问其父级`<select>`元素的`selectedIndex`属性,强迫浏览器计算`<option>`的`selected`属性,
以得到正确的值。需要注意的是`<option>`元素的父元素不一定是`<select>`,也有可能是`<optgroup>`。具体代码如下:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (!support.optSelected) {
var parent = option.parentNode;
parent.selectedIndex;
//处理optgroup时的情况
if (parent.parentNode) {
parent.parentNode.selectedIndex;
}
}
return option.selected;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
if ( name === "selected" && !jQuery.support.optSelected ) {
var parent = elem.parentNode;
if ( parent ) {
parent.selectedIndex;
// Make sure that it also works with optgroups, see #5701
if ( parent.parentNode ) {
parent.parentNode.selectedIndex;
}
}
}
// If applicable, access the attribute via the DOM 0 way
if ( name in elem && notxml && !special ) {
if ( set ) {
// We can't allow the type property to be changed (since it causes problems in IE)
// rtype = /(button|input)/i,
// button 与 input 不允许修改 type属性
if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
jQuery.error( "type property can't be changed" );
}
elem[ name ] = value;
}
// browsers index elements by id/name on forms, give priority to attributes.
// 元素为form
if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
return elem.getAttributeNode( name ).nodeValue;
}
// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
if ( name === "tabIndex" ) {
var attributeNode = elem.getAttributeNode( "tabIndex" );
return attributeNode && attributeNode.specified ?
attributeNode.value :
rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
0 :
undefined;
}
return elem[ name ];
}
if ( !jQuery.support.style && notxml && name === "style" ) {
if ( set ) {
elem.style.cssText = "" + value;
}
return elem.style.cssText;
}
if ( set ) {
// convert the value to a string (all browsers do this but IE) see #1070
elem.setAttribute( name, "" + value );
}
var attr = !jQuery.support.hrefNormalized && notxml && special ?
// Some attributes require a special call on IE
elem.getAttribute( name, 2 ) :
elem.getAttribute( name );
// Non-existent attributes return null, we normalize to undefined
return attr === null ? undefined : attr;
}
// elem is actually elem.style ... set the style
// Using attr for specific style information is now deprecated. Use style instead.
return jQuery.style( elem, name, value );
}
});