.prop() vs .attr()
.prop() vs .attr()
所以 jQuery 1.6 有了新的函数 prop()
。
$(selector).click(function(){ //instead of: this.getAttribute('style'); //do i use: $(this).prop('style'); //or: $(this).attr('style'); })
或者在这种情况下,它们做的事情相同吗?
如果我确实需要切换到使用 prop()
,所有旧的 attr()
调用会在切换到 1.6 后停止工作吗?
更新
selector = '#id' $(selector).click(function() { //instead of: var getAtt = this.getAttribute('style'); //do i use: var thisProp = $(this).prop('style'); //or: var thisAttr = $(this).attr('style'); console.log(getAtt, thisProp, thisAttr); });
test
(查看这个 jsfiddle: http://jsfiddle.net/maniator/JpUF2/)
控制台将 getAttribute
和 attr
记录为字符串,但将 prop
记录为 CSSStyleDeclaration
,为什么?这将如何影响我未来的编码?
我认为 Tim表达得很好,但我们先回到基本概念:
DOM 元素是一个对象,是内存中的事物。和大多数 OOP 中的对象一样,它有属性。另外,它还有一个定义在元素上的属性映射(通常来自浏览器用于创建元素的标记语言)。元素的某些属性从具有相同或类似名称的属性中获取初始值(如value
从"value"属性中获取初始值; href
从 "href"属性中获取初始值,但不是完全相同的值; className
从 "class"属性获取)。其他属性以其他方式获得它们的初始值:例如,parentNode
属性基于其父元素而取值; 一个元素始终具有style
属性,无论它是否具有 "style"属性。
考虑一个页面上的锚点http://example.com/testing.html
:
Hi
一些任意的 ASCII 艺术(省略了许多内容):
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | HTMLAnchorElement | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | href: "http://example.com/foo.html" | | name: "fooAnchor" | | id: "fooAnchor" | | className: "test one" | | attributes: | | href: "foo.html" | | name: "fooAnchor" | | id: "fooAnchor" | | class: "test one" | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
注意属性和属性值是不同的。
虽然它们是不同的,但由于所有这些都是演变而来而不是从零开始设计,因此一些属性在设置时会写回它们所派生的属性,但并不是所有属性都会写回,正如上面的href
所示,映射并不总是简单的 "传递值",有时涉及解释。
当我说属性是对象的属性时,我并不是在抽象地说话。下面是一些非 jQuery 代码:
var link = document.getElementById('fooAnchor'); alert(link.href); // alerts "http://example.com/foo.html" alert(link.getAttribute("href")); // alerts "foo.html"
(这些值是根据大多数浏览器确定的;存在一些差异。)
link
对象是一个真实的事物,您可以看到在其上访问属性和访问属性的区别。
正如 Tim 所说,绝大部分时间,我们希望使用属性。这部分原因是它们的值(甚至它们的名称)在各个浏览器之间更加一致。我们通常只在没有属性与之关联(自定义属性)时,或者当我们知道该特定属性的属性值和元素属性不是1:1时,才使用属性。
标准属性是在各种DOM规范中进行布局:
这些规范都有很好的索引,我建议随时保留与它们的链接;我一直使用它们。
自定义属性可以包括您可能放置在元素上的任何data-xyz
属性,以向您的代码提供元数据(现在在HTML5中是有效的,只要您坚持使用data-
前缀)。 (最近版本的jQuery通过data
函数使您可以访问data-xyz
元素,但是该函数不仅仅是访问data-xyz
属性[它会执行更多或更少的操作],除非您实际需要它的功能,否则我会使用attr
函数与data-xyz
属性交互。)
attr
函数曾经在获取它们认为您想要的内容方面具有一些复杂的逻辑,而不是逐字获取属性。 它混淆了这些概念。转向prop
和attr
旨在解决它们之间的紧密联系。在jQuery的v1.6.0中,短暂地走得太远了,但是功能很快就被新增回来,以处理人们在技术上应该使用prop
而使用attr
的常见情况。
2012年11月1日更新
我的原始答案特指jQuery 1.6。我的建议仍然有效,但jQuery 1.6.1稍微改变了一些东西:面对预测中的众多网站故障,jQuery团队将attr()
回退到与以前相似(但不完全相同)的行为,用于布尔属性。John Resig也在博客中谈到了。我可以看到他们所处的困难,但仍不同意他倾向于使用attr()
的建议。
原始答案
如果你只使用过jQuery而没有直接使用DOM,这可能是一个令人困惑的变化,尽管从概念上讲这肯定是一个改进。这对于无数使用jQuery的网站来说并不是好消息,因为它们将因此受到破坏。
我总结了主要问题:
- 通常,你需要使用
prop()
而不是attr()
。 - 在大多数情况下,
prop()
执行的是attr()
曾经执行的任务。在你的代码中将attr()
调用替换为prop()
通常是有效的。 - 属性通常比属性更简单处理。属性值可能只是一个字符串,而属性可以是任何类型。例如,
checked
属性是布尔类型的,style
属性是一个具有每种样式的单独属性的对象,size
属性是一个数字。 - 如果存在具有相同名称的属性和属性,则通常更新一个将更新另一个,但对于输入的某些属性(如
value
和checked
),情况并非如此:对于这些属性,属性始终表示当前状态,而属性(除了旧版本的IE之外)对应于输入的默认值/选中状态(反映在defaultValue
/defaultChecked
属性中)。 - 此更改消除了jQuery固定在属性和属性前面的一些神奇层,意味着jQuery开发人员将不得不了解属性和属性之间的区别。这是一件好事。
如果您是jQuery开发人员,并且对于属性和属性整个业务感到困惑,那么您需要退后一步,并学习一些相关知识,因为jQuery不再尝试如此努力地保护您的代码。对于主题的官方,但有点枯燥的话,有规范:DOM4,HTML DOM,DOM Level 2,DOM Level 3。Mozilla的DOM文档适用于大多数现代浏览器,并且比规范更易于阅读,因此您可能会发现他们的DOM参考有所帮助。有一个有关元素属性的部分。
举个例子来说,属性比属性更简单易处理。考虑一个最初被选中的复选框,这里是两种可能的有效的HTML代码:
那么用jQuery如何找出是否选中复选框呢?在Stack Overflow上,你通常会找到以下建议:
if ( $("#cb").attr("checked") === true ) {...}
if ( $("#cb").attr("checked") == "checked" ) {...}
if ( $("#cb").is(":checked") ) {...}
这其实是世界上最简单的事情,使用自1995年以来在每个重要的可脚本浏览器中存在且无缺陷的布尔属性checked
即可:
if (document.getElementById("cb").checked) {...}
该属性还使得选择或取消选择复选框变得微不足道:
document.getElementById("cb").checked = false
在jQuery 1.6中,这变成了一项不含歧义的操作:
$("#cb").prop("checked", false)
使用checked
属性来脚本化复选框是毫无帮助和必要的。你需要的是属性。
- 使用
checked
属性检查或取消复选框的正确方法并不明显 - 属性值反映默认值,而不是当前可见状态(除了一些旧版本的IE,这使得事情仍然更加困难)。该属性没有提供关于页面上复选框是否被选中的信息。请参见http://jsfiddle.net/VktA6/49/。