.attr()和.prop()和.css()的区别
是不是新手都会遇到这个问题?遇到过一次,在网上搜一搜,综合成了下面这样。重点参考了dolphin的‘jQuery的attr与prop’, 写的很清楚呢。
一般attribute翻译成中文术语为“特性”,property翻译成中文术语为“属性”.
1.attribute
attribute 可以看作是一个特性节点,每个DOM元素都有一个对应的 attributes属性来存放所有的attribute节点,attributes是一个类数组的容器。
<div id='divId' customizedV='value1'></div>,对于这个div元素来说,他的attributes里就存了两个attribute节点,类似于这样:[id:'divId',customizedV:'value1']。
可以这样来访问attribute节点:
obj.attributes[0].id;//divId
obj.attributes[1].customizedV;//value1。
但是 IE6-7将很多东西都存放在attributes中,上面的访问方法和标准浏览器的返回结果又不同,所以 通常获取一个attribute特性值用
obj.getAttribute(vName)、obj.setAttribute('vName','value')、obj.removeAttribute('vName') 。
对于添加的自定义attribute会显示在html文件里(用.attr()取那些已经显示在html里的特性肯定是不会出错的),非自定义的attribute虽然有些并没有显示在html里,本以为会有一个默认值, 但是对chrome测试发现,没有显式的设置attribute的值,就无法getgetAttribute。如:
<input id='myInputId' type="checkbox" >
alert(obj.getAttribute('checked'));//null
alert($(obj).attr('checked'));//undefined
对<img src='title.gif'>的alt也是如此。
结论:obj.getAttribute(vName)、obj.setAttribute('vName','value')、obj.removeAttribute('vName')和$(obj).attr()只能操作显式写在Dom节点里的特性,这些特性可以看作是节点的一部分组成成员。
2.property
property是DOM对象的一个字段,跟我们平常使用的对象的字段/属性一样,取值或者设置值和普通字段一样直接通过”对象.字段“的方式。比如添加的自定义property就直接是obj.myOwnProp='value2';设置的property不会显示在html文件里。你是不是在想:这样不就可以利用property在节点上存储一些自己的信息流么?在IE9之前版本中,如果property没有在DOM元素被移除之前删除,使用.prop()方法设置DOM元素property(简单类型除外:number、string、boolean)的值会导致内存泄露。为了安全的设置DOM对象的值,避免内存泄露,可以使用jQuery专门在元素上存放数据的方法:.data()方法。
对于<input id='myInputId'>,可以在chrome看到列出来这个inputDom对象的字段:
结论:property是DOM节点对象的一个字段,跟我们平常使用的对象的字段/属性一样,除了内置的一些属性(如checkbox有checked属性、disabled属性),也可以设置自定义属性(但是属性值只限于简单类型)。
3、为什么容易混淆
看似二者并不相关,容易混淆是因为:DOM对象的一些property属性和attribute特性名字或值是一样的。
如id和checked既是特性名也是属性名:obj.getAttribute(id)和obj.id都能取得id的值。
但是并不是所有的attribute与对应的property名字都一致,如attribute 的class对应property的是className。
3.1、attribute和property共享数据,attribute更改了会对property造成影响,反之亦然。如:
obj.setAttribute('class','class1');
obj.className='class2';
console.log(obj.getAttribute('class'));//class2。
但是两者的自定义属性是独立的数据,即使name一样,也互不影响。如:
obj.setAttribute(' customizedV','value1');
obj.customizedV=’value2’;
console.log(obj.getAttribute(customizedV')); //value1。
但是IE6、7没有作区分,自定义属性数据也是共享的。
结论:由于一些Dom节点的attribute和property具有共同的名字或值,所以二者容易混淆,但是又由于二者之间共享数据,一个改变了,另一个也会自动改变。所以需要操作它们时,只要设置二者之中的任何一个就可以了。对于自定义的特性和属性,二者是独立的,互不影响(即使二者名字相同),但由于IE6、7对自定义的特性和属性也是共享数据,所以最好不要取一样的名字。
3.2、对于值是true/false的property,如input:checkbox的checked等,attribute取的值是HTML文档字面量值,property取的是计算结果。
在chrome中测试:
在<input id='myInputId' type="checkbox">添加如下特性:
check
或checked=""
或checked=0
或checked='false'
或checked= false
此时checkbox都是选中状态,
可以通过obj.checked=false或obj.removeAttribute('checked')使它处于不选择状态。
结论:property值为true/false对应的attribute(如果有的话)的值有点特别,只要在dom节点里添加了这个attribute,不管它的值是什么(不管setAttribute('checked',value)中的value是什么)都与property=true的效果是一样的,只有removeAttribute才能改变property为false。
3.3、对于值是true/false的property,如input:checkbox的checked等,property的改变并不影响attribute字面量,但是attribute改变会影响property计算。
有一点很重要:property值为true/false对应的attribute,以checked为例。实际上这个checked特性并不是与checked属性一致,而是与defaultChecked属性一致。所以如果节点<input checked>,然后设置obj.checked=false;使它处于不选中状态,再obj.setAttribute('checked','true');此时它依然处于不选中状态。所以checked特性应该只用来在节点里初始化,后期改变状态在原生js里都只用checked属性来控制。 另外,jquery的.attr()对原始的.setAttribute、.getAttribute作了修改,使.attr('checked',true)和.attr('checked',false)效果与设置obj.checked属性一致了,并且jquery的.attr('checked')只返回‘checked'(节点中设置了checked特性或通过.attr或.setAttribute设置了特性)和'undefined'(即使设置了checked属性为true)
3.4、对于一些和路径相关的属性,两者取得值也不尽相同,但是同样attribute取得是字面量,property取得是计算后的完整路径。如:
对于<a id="test4" href="#">Click</a>
var obj=document.getElementById('test4');
alert(obj.getAttribute('href')); //#
alert(obj.href); //file:///C:/Users/bsun/Desktop/ss/anonymous.html#
4、.css()与它们的区别自然很明显了,这个方法只能用来获取/设置DOM对象的样式。
如color、background,对应js里的obj.style.样式名=样式值。