jQuery中的attr()和prop()
对于attr()方法应该都比较熟悉,但是在jQuery1.6版本及之后,引入了一个新的方法prop(),实现的功能又很相似,这就带来了不少困惑。
在英文中,attribute和property一般都作为“属性”来翻译,硬是将其拆分成两个概念来理解,确实有点不好接受。这里,为区分起见,我将attribute译为“属性”,property译为“特性”(可能您觉得翻过来更合适,不纠结这个问题了。当然,如果您有更好的译法,还请补充)。
1. 为什么要引入prop()方法?
jQuery作者John Resig在其博客中关于这个问题有比较详尽的解释。简单的说,有两个原因:
1)为了更方便的访问DOM的特性(properties)。举例来说,比如在1.6之前的版本,可能需要这样来做:
var elem = $("#foo")[0]; if ( elem ) { index = elem.selectedIndex; }
访问其他诸如nodeName、defaultValue等特性也是一样。但是引入prop()方法之后就简单了:
index = $("#foo").prop("selectedIndex");
2)由于实现时attr()方法要调用prop()方法,因此直接使用prop()速度会更快。
2. 特性(properties)和属性(attributes)有何区别?
DOM对象大部分的property都有对应的attribute,名字也基本一样(也有例外,如“class”这个attribute对应的property名字为“className”),这些property也和其对应的attribute保持一样的状态或值。但一些Boolean类型的属性(如checked, selected, disabled等)有些特殊,其attribute只保留初始值(默认值), property才是当前最新的状态或值。如一个默认勾选的checkbox,当你在页面去除勾选的时候,checked这个property已由true变为false,而checked这个attribute仍然保持“checked”这个初始值。由此可见attribute和property完全不是同一个东西,但“通用”的attr方法似乎在某种程度上模糊了这个区别。
3. attr()和prop()有何区别?
使用prop的时候,返回值是标准属性,true/false,比如$('#checkbox').prop('disabled'),不会返回“disabled”或者“”,只会是true/false。当然赋值的时候也是如此。使用attr,如disabled='disabled'时,为true,没有选中时,则为undefined。如此,我们便统一了所有操作,无论是从语法上还是语义上。
.prop()方法应该被用来处理boolean attributes/properties以及在html(比如:window.location)中不存在的properties。其他所有的attributes可以而且应该继续使用.attr()方法来进行操作。
具体的使用示例可以参考官方API文档。
4. 哪些属性应该用prop()方法呢?
简单的说,那些只添加属性名不添加属性值就会生效,或者是,只存在true/false的属性就需要使用prop()方法,比如selectedIndex
, tagName
, nodeName
, nodeType
, ownerDocument
, defaultChecked
, 和 defaultSelected
。官方给出的区分如下:
Attribute/Property | .attr() | .prop() |
---|---|---|
accesskey | ✓ | |
align | ✓ | |
async | ✓ | ✓ |
autofocus | ✓ | ✓ |
checked | ✓ | ✓ |
class | ✓ | |
contenteditable | ✓ | |
draggable | ✓ | |
href | ✓ | |
id | ✓ | |
label | ✓ | |
location ( i.e. window.location ) | ✓ | ✓ |
multiple | ✓ | ✓ |
readOnly | ✓ | ✓ |
rel | ✓ | |
selected | ✓ | ✓ |
src | ✓ | |
tabindex | ✓ | |
title | ✓ | |
type | ✓ | |
width ( if needed over .width() ) |
✓ |
5. 举例说明。
例如,考虑一个DOM元素的HTML标记中定义的<input type="checkbox" checked="checked" />
,并假设它是一个JavaScript变量命名的elem
:
elem.checked |
true (Boolean) 将改变复选框的状态 |
---|---|
$(elem).prop("checked") |
true (Boolean) 将改变复选框的状态 |
elem.getAttribute("checked") |
"checked" (String) 不会改变的复选框的初始状态; |
$(elem).attr("checked") (1.6) |
"checked" (String) 不会改变的复选框的初始状态; |
$(elem).attr("checked") (1.6.1+) |
"checked" (String) 将改变复选框的状态 |
$(elem).attr("checked") (pre-1.6) |
true (Boolean) 将改变复选框的状态 |
根据W3C的表单规范 ,在checked
属性是一个布尔属性,这意味着只要该 attribute 存在,即使它没有值,或是一个空字符串,该属性对应的 property 就是 true
。以下推荐的是兼容浏览器方式,判断 checkbox 元素的 checked 属性是否为"真" 的方法:
if ( elem.checked )
if ( $(elem).prop("checked") )
if ( $(elem).is(":checked") )
如果你使用jQuery 1.6 ,代码if ( $(elem).attr("checked") )
,将获得一个属性(attribute) ,它不改变该复选框被选中和选中。它只是用来存储默认或选中属性的初始值。为了保持向后兼容,.attr()
方法从 jQuery 1.6.1+ 开始除了返回属性值外,还会更新 property 属性,因此 boolean attribute(布尔属性)不需要通过 .prop()
来改变其值。推荐使用上述方法之一,来取得 checked 的值。