.prop()与. attr()

因此, jQuery 1.6具有新的功能prop()

$(selector).click(function(){
    //instead of:
    this.getAttribute('style');
    //do i use:
    $(this).prop('style');
    //or:
    $(this).attr('style');
})

还是在这种情况下他们做同样的事情?

如果我确实必须切换到使用prop() ,那么如果我切换到 1.6,所有旧的attr()调用都会中断?

更新

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);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div id='id' style="color: red;background: orange;">test</div>

(另请参见此提琴: http : //jsfiddle.net/maniator/JpUF2/

控制台将getAttribute作为字符串记录,将attr作为字符串记录,但将prop作为CSSStyleDeclaration ,为什么?将来如何影响我的编码?

答案

2012 年 11 月 1 日更新

我的原始答案专门适用于 jQuery 1.6。我的建议保持不变,但 jQuery 1.6.1 进行了一些细微更改:面对预期的一堆破损网站,jQuery 团队将attr()恢复为接近(但不完全相同)的布尔属性旧行为。 。约翰 · 雷西格(John Resig)也对此发表了博客 。我可以看到他们遇到的困难,但仍然不同意他对attr()推荐。

原始答案

如果您只使用过 jQuery,而没有直接使用过 DOM,则这可能是一个令人困惑的更改,尽管从概念上来说这绝对是一种改进。对于使用 jQuery 的成千上万的网站来说,效果不是很好,但是由于此更改,这些网站将中断。

我将总结主要问题:

  • 您通常需要prop()而不是attr()
  • 在大多数情况下, prop()执行attr()过去的工作。通常,可以在代码中用prop()替换对attr()调用。
  • 属性通常比属性更容易处理。属性值只能是字符串,而属性可以是任何类型。例如, checked属性是一个布尔值, style属性是一个对象,每个对象都有各自的属性, size属性是一个数字。
  • 当一个属性和一个具有相同名称的属性同时存在时,通常更新一个属性会更新另一个属性,但是对于某些输入属性(例如valuechecked则不是这种情况:对于这些属性,该属性始终表示当前状态而属性(旧版 IE 中除外)对应于输入的默认值 / 检查(反映在defaultValue / defaultChecked属性中)。
  • 这项更改消除了固定在属性和属性前面的 jQuery 魔术层,这意味着 jQuery 开发人员将不得不学习一些有关属性和属性之间差异的知识。这是一件好事。

如果您是 jQuery 开发人员,并且对整个业务都对属性和属性感到困惑,那么您需要退后一步,并对其有所了解,因为 jQuery 不再那么努力地使您远离这些东西。对于有关该主题的权威性但有些措手不及的单词,有以下规范: DOM4HTML DOMDOM Level 2DOM Level 3 。 Mozilla 的 DOM 文档对大多数现代浏览器均有效,并且比规范更易于阅读,因此您可能会发现其DOM 参考有用。 关于元素属性的一

作为如何比属性更容易处理属性的示例,请考虑一个最初选中的复选框。这是有效的 HTML 可能有两个片段:

<input id="cb" type="checkbox" checked>
<input id="cb" type="checkbox" checked="checked">

那么,如何确定 jQuery 是否选中了该复选框?查看堆栈溢出,通常会发现以下建议:

  • if ( $("#cb").attr("checked") === true ) {...}
  • if ( $("#cb").attr("checked") == "checked" ) {...}
  • if ( $("#cb").is(":checked") ) {...}

实际上,这是世界上最简单的事情:使用checked Boolean 属性,自 1995 年以来,该属性在每个主要的可编写脚本的浏览器中都已经存在并且可以完美地工作:

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/

我认为蒂姆说得很好 ,但让我们退后一步:

DOM 元素是对象,是内存中的东西。像 OOP 中的大多数对象一样,它具有properties 。它还分别具有在元素上定义的属性的映射(通常来自浏览器为创建元素而读取的标记)。有些元素的属性从具有相同或相似名称的属性 (获取其初始value从 “值” 属性获取其初始值; href从 “href” 属性获取其初始值,但它不是完全一样的值; 来自 “class” 属性的className )。其他属性以其他方式获取其初始值:例如, parentNode属性根据其父元素是什么来获取其值;元素始终具有style属性,无论它是否具有 “样式” 属性。

让我们考虑一下http://example.com/testing.html页面中的锚点:

<a href='foo.html' class='test one' name='fooAnchor' id='fooAnchor'>Hi</a>

一些免费的 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 时(如上述href和 “href”) )。

在各种 DOM 规范中列出了标准属性:

这些规范具有出色的索引,我建议您随时保持指向它们的链接;我一直都在用它们。

自定义属性包括,例如,您可能会在元素上放置的任何data-xyz属性,以向代码提供元数据(现在,从 HTML5 开始,只要您坚持使用data- prefix, data- )。 (jQuery 的最新版本使您可以通过data函数访问data-xyz元素,但是该函数不仅data-xyz属性的访问器 [它做的更多和更少];除非您确实需要它的功能,否则我将使用attr函数与data-xyz属性进行交互。)

attr函数过去在获取他们认为想要的东西时有一些复杂的逻辑,而不是从字面上获取属性。它混淆了这些概念。转向propattr是要取消它们的合并。简而言之,在 v1.6.0 中 jQuery 在这方面走得太远了,但是功能很快就被添加回 attr以处理人们在技术上应该使用prop时使用attr的常见情况。

对于 jQuery 来说,这种变化已经很长时间了。多年来,他们一直对名为attr()的函数感到满意,该函数主要检索 DOM 属性,而不是您期望从名称中获得的结果。 attr()prop()的隔离应该有助于减轻 HTML 属性和 DOM 属性之间的某些混淆。 $.fn.prop()指定的 DOM 属性,而$.fn.attr()指定的 HTML 属性。

为了完全理解它们是如何工作的,下面对 HTML 属性和 DOM 属性之间的区别进行了扩展说明:

HTML 属性

句法:

<body onload="foo()">

目的:允许标记具有与之相关联的数据,以用于事件,渲染和其他目的。

可视化: HTML属性 class 属性在此处显示在主体上。可通过以下代码进行访问:

var attr;
attr = document.body.getAttribute("class");
//IE 8 Quirks and below
attr = document.body.getAttribute("className");

属性以字符串形式返回,并且在浏览器之间可能不一致。但是,它们在某些情况下可能至关重要。如上所示,IE 8 Quirks 模式(及以下版本)期望 get / set / removeAttribute 中的 DOM 属性名称而不是属性名称。这是了解差异很重要的众多原因之一。

DOM 属性

句法:

document.body.onload = foo;

目的:允许访问属于元素节点的属性。这些属性类似于属性,但是只能通过 JavaScript 访问。这是一个重要的区别,有助于阐明 DOM 属性的作用。 请注意,属性与 properties 完全不同 ,因为此事件处理程序分配是无用的,并且不会接收该事件(主体没有 onload 事件,只有 onload 属性)。

可视化: DOM属性

在这里,您会注意到 Firebug 中 “DOM” 选项卡下的属性列表。这些是 DOM 属性。您会立即注意到其中的很多,因为您在不知不觉中就已经使用过它们。它们的值就是您将通过 JavaScript 收到的值。

文献资料

HTML: <textarea id="test" value="foo"></textarea>

JavaScript: alert($('#test').attr('value'));

在早期版本的 jQuery 中,这将返回一个空字符串。在 1.6 中,它返回适当的值foo

不用看这两个函数的新代码,我可以自信地说,混淆更多是与 HTML 属性和 DOM 属性之间的差异有关,而不是与代码本身有关。希望这可以为您解决一些问题。

- 马特

属性在 DOM 中; HTML 中的一个属性被解析为 DOM。

更多细节

如果更改属性,则更改将反映在 DOM 中(有时使用不同的名称)。

示例:更改标签的class属性将更改 DOM 中该标签的className属性。如果标签上没有属性,则仍然具有带有空值或默认值的相应 DOM 属性。

示例:尽管您的标签没有class属性,但是 DOM 属性className确实存在,并且具有空字符串值。

编辑

如果更改一个,则另一个将由控制器更改,反之亦然。该控制器不在 jQuery 中,而是在浏览器的本机代码中。

只是 HTML 属性和 DOM 对象之间的区别引起了混乱。对于那些this.src使用 DOM 元素本机属性(例如this.src this.value this.checked等)的人, .prop非常欢迎家庭使用。对于其他人,这只是增加了一层混乱。让我们澄清一下。

下面的示例是查看.attr.prop之间差异的最简单方法:

<input blah="hello">
  1. $('input').attr('blah') :按预期返回'hello' 。这里没有惊奇。
  2. $('input').prop('blah') :返回undefined - 因为它正在尝试执行[HTMLInputElement].blah且该 DOM 对象上不存在此类属性。它仅在范围内作为该元素的属性存在,即[HTMLInputElement].getAttribute('blah')

现在,我们进行如下更改:

$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');
  1. $('input').attr('blah') :返回'apple'吗?为什么不将 “梨” 设置为该元素的最后一个。因为属性是在输入属性上更改的,而不是 DOM 输入元素本身的更改 - 它们基本上几乎彼此独立地工作。
  2. $('input').prop('blah') :返回'pear'

出于上述原因,您真正需要注意的事情就是不要在整个应用程序中同一属性混合使用这些方法

看到证明不同的小提琴: http : //jsfiddle.net/garreh/uLQXc/


.attr.prop

第一轮:风格

<input style="font:arial;"/>
  • .attr('style') - 返回匹配元素的内联样式,即"font:arial;"
  • .prop('style') - 返回样式声明对象,即CSSStyleDeclaration

第二回合:价值

<input value="hello" type="text"/>   

$('input').prop('value', 'i changed the value');
  • .attr('value') - 返回'hello' *
  • .prop('value') - 返回'i changed the value'

* 注意:出于这个原因,jQuery 具有.val()方法,该方法在内部等效于.prop('value')

TL; DR

在大多数情况下,在attr()使用prop()

属性是输入元素的当前状态。 属性是默认值。

一个属性可以包含不同类型的事物。属性只能包含字符串

脏检查

这个概念提供了一个可以观察到差异的示例: http : //www.w3.org/TR/html5/forms.html#concept-input-checked-dirty

试试看:

  • 单击按钮。两个复选框都被选中。
  • 取消选中两个复选框。
  • 再次单击该按钮。只有prop复选框被选中。砰!

$('button').on('click', function() {
  $('#attr').attr('checked', 'checked')
  $('#prop').prop('checked', true)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>attr <input id="attr" type="checkbox"></label>
<label>prop <input id="prop" type="checkbox"></label>
<button type="button">Set checked attr and prop.</button>

对于某些属性(如button disabled ,添加或删除内容属性disabled="disabled"总是会切换属性(在 HTML5 中称为 IDL 属性),因为http://www.w3.org/TR/html5/forms.html#attr -fe-disabled说:

禁用的 IDL 属性必须反映禁用的内容属性。

因此尽管它很丑陋,因为它不需要修改 HTML,但您可能会摆脱它。

对于其他属性,例如input type="checkbox" checked="checked"上的checked="checked" ,事情就中断了,因为一旦单击它,它就会变脏,然后添加或删除checked="checked"内容属性将不再切换 checkness

这就是为什么您应该主要使用.prop ,因为它直接影响有效属性,而不是依赖于修改 HTML 的复杂副作用。

全部都在文档中

属性和属性之间的差异在特定情况下可能很重要。在 jQuery 1.6 之前,.attr()方法在检索某些属性时有时会考虑属性值,这可能会导致行为不一致。从 jQuery 1.6 开始,.prop()方法提供了一种显式检索属性值的方法,而. attr()则检索属性。

所以使用道具!

属性位于 HTML 文本文档 / 文件中 (== 想象这是您解析 html 标记的结果),而
属性位于 HTML DOM 树中 (== 基本上是 JS 意义上某个对象的实际属性)。

重要的是,它们中的许多都是同步的(如果更新class属性,则 html 中的class属性也会被更新;否则)。 但是某些属性可能会同步到意外的属性 - 例如, checked 属性对应于属性 defaultChecked ,因此

  • 手动选中复选框将更改.prop('checked')值,但不会更改.attr('checked').prop('defaultChecked')
  • 设置$('#input').prop('defaultChecked', true)也会更改.attr('checked') ,但这在元素上不可见。

经验法则是.prop()方法应用于布尔属性 / 属性以及 html 中不存在的属性(例如 window.location)。所有其他属性(可以在 html 中看到的属性)都可以并且应该继续使用.attr()方法进行操作。 ( http://blog.jquery.com/2011/05/10/jquery-1-6-1-rc-1-released/

下表显示了首选.prop()位置(即使仍然可以使用.attr() )。

首选用法的表


在正式建议使用后者的情况下,为什么有时要使用. prop()而不是. attr()?

  1. .prop()可以返回任何类型 - 字符串,整数,布尔值; .attr()始终返回一个字符串。
  2. .prop().attr()快约 2.5 倍。

.attr()

  • 获取匹配元素集中第一个元素的属性值。
  • 给您元素的值,就像在页面加载时在 html 中定义的那样

.prop()

  • 获取匹配元素集中第一个元素的属性值。
  • 给出通过 javascript / jquery 修改的元素的更新值