.prop() 与 .attr()

Posted

技术标签:

【中文标题】.prop() 与 .attr()【英文标题】:.prop() vs .attr() 【发布时间】:2011-08-17 23:52:13 【问题描述】:

所以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,为什么?这对我以后的编码有何影响?

【问题讨论】:

这肯定会引起人们的兴趣:books.google.ca/… @Neal,因为这个改变超越了 jQuery。 html 属性和 DOM 属性之间的区别是巨大的。 看到 jQuery 恢复了更改让我很伤心。他们正朝着错误的方向前进。 @Neal。是的,它只是使问题进一步复杂化,而不是将这两种方法分开。 @BritishDeveloper 答案比简单地说明总是使用 x 或 y 更复杂,因为这取决于你想要得到什么。你想要属性,还是想要属性?它们是两种截然不同的东西。 【参考方案1】:

全部在the doc:

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

所以使用道具!

【讨论】:

【参考方案2】:

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

为了完全理解它们是如何工作的,这里有一个关于 HTML 属性和 DOM 属性之间区别的扩展解释。:

HTML 属性

语法:

&lt;body onload="foo()"&gt;

目的: 允许标记具有与其关联的数据以用于事件、呈现和其他目的。

可视化: 类属性显示在主体上。可通过以下代码访问:

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

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

DOM 属性

语法:

document.body.onload = foo;

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

可视化:

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

文档

JavaScript: The Definitive Guide by David Flanagan HTML Attributes, Mozilla Dev Center DOM Element Properties, Mozilla Dev Center

示例

HTML:&lt;textarea id="test" value="foo"&gt;&lt;/textarea&gt;

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

在早期版本的 jQuery 中,这会返回一个空字符串。在 1.6 中,它返回正确的值,foo

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

-马特

【讨论】:

$.prop() 获取 DOM 属性,$.attr() 获取 HTML 属性。我试图在心理上弥合差距,以便您了解两者之间的区别。 男孩,我现在也很困惑。所以$('#test').prop('value') 不返回任何东西? .attr('checked') 也不是复选框?但是以前呢?现在您必须将其更改为prop('checked')?我不明白这种区分的必要性——为什么区分 HTML 属性和 DOM 属性很重要? “很长一段时间” 的常见用例是什么?抽象出两者之间的区别有什么错误,因为它们的用例似乎大多重叠?【参考方案3】:

2012 年 11 月 1 日更新

我的原始答案专门适用于 jQuery 1.6。我的建议保持不变,但 jQuery 1.6.1 稍微改变了一些事情:面对预测的一堆损坏的网站,jQuery 团队 reverted attr() to something close to (but not exactly the same as) its old behaviour for Boolean attributes。 John Resig 也blogged about it。我可以看到他们遇到的困难,但仍然不同意他选择attr() 的建议。

原答案

如果您只使用过 jQuery 而不是直接使用 DOM,这可能是一个令人困惑的变化,尽管它在概念上绝对是一个改进。但是,对于使用 jQuery 的无数网站来说并不是那么好,但会因为这种变化而崩溃。

我将总结主要问题:

您通常需要prop() 而不是attr()。 在大多数情况下,prop() 执行 attr() 过去所做的事情。在您的代码中用prop() 替换对attr() 的调用通常会起作用。 属性通常比属性更容易处理。属性值只能是字符串,而属性可以是任何类型。例如,checked 属性是布尔值,style 属性是具有每种样式的单独属性的对象,size 属性是数字。 如果同时存在同名的属性和属性,通常更新一个会更新另一个,但输入的某些属性并非如此,例如valuechecked:对于这些属性,属性始终表示当前状态,而属性(旧版本的 IE 除外)对应于输入的默认值/检查性(反映在 defaultValue / defaultChecked 属性中)。 此更改移除了 jQuery 卡在属性和属性前面的一些魔术层,这意味着 jQuery 开发人员必须了解一下属性和属性之间的区别。这是一件好事。

如果你是一个 jQuery 开发人员,并且对属性和属性的整个业务感到困惑,你需要退后一步,了解一下,因为 jQuery 不再努力保护你免受这些东西的影响.对于该主题的权威但有些干涩的词,有规格:DOM4、HTML DOM、DOM Level 2、DOM Level 3。 Mozilla 的 DOM 文档适用于大多数现代浏览器,并且比规范更易于阅读,因此您可能会发现他们的 DOM reference 很有帮助。有一个section on element properties。

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

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

那么,你如何确定复选框是否被 jQuery 选中?查看 Stack Overflow,您通常会发现以下建议:

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

这实际上是世界上与 checked 布尔属性相关的最简单的事情,自 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/。

【讨论】:

@Neal:DOM 元素是一个对象。属性是该对象的属性,就像任何其他编程对象一样。其中一些道具从标记中的属性中获取初始值,这些属性也存储在 DOM 对象中的 separate 属性映射中。在大多数情况下,写入道具只会更改道具,尽管遗憾的是有些道具会将任何更改写入底层 attr(例如value),但让我们尽量忽略这一点。 99% 的时间,您都想使用道具。如果您需要使用实际属性,您可能会知道。【参考方案4】:

我认为Tim said it quite well,但让我们退后一步:

DOM 元素是一个对象,是内存中的一个东西。像 OOP 中的大多数对象一样,它具有 属性。它还分别具有元素上定义的属性的映射(通常来自浏览器为创建元素而读取的标记)。某些元素的 properties 从具有相同或相似名称的 attributes 中获取它们的 initial 值(value 从“值" 属性;href 从 "href" 属性中获取其初始值,但它不是完全相同的值;className 来自 "class" 属性)。其他属性以其他方式获取其初始值:例如,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" | |名称:“fooAnchor”| | id: "fooAnchor" | |类名:“测试一”| |属性:| | href: "foo.html" | |名称:“fooAnchor”| | id: "fooAnchor" | |类:“测试一”| +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

注意属性和属性是不同的。

现在,虽然它们是不同的,但由于所有这些都是演变的,而不是从头开始设计的,如果您设置它们,许多属性会写回它们派生的属性。但并非所有人都这样做,从上面的href 可以看出,映射并不总是直接“传递值”,有时会涉及到解释。

当我谈论属性是对象的属性时,我并不是在抽象地谈论。下面是一些非 jQuery 代码:

var link = document.getElementById('fooAnchor');
alert(link.href);                 // alerts "http://example.com/foo.html"
alert(link.getAttribute("href")); // alerts "foo.html"

(这些值与大多数浏览器一致;存在一些差异。)

link 对象是真实的,您可以看到访问其上的属性和访问属性之间存在真正的区别。

正如蒂姆所说,绝大多数,我们希望与属性合作。部分原因是它们的值(甚至它们的名称)在浏览器之间往往更加一致。我们大多只想在没有与之相关的属性(自定义属性)时使用属性,或者当我们知道对于该特定属性,属性和属性不是 1:1 时(如 href 和 "href ”)。

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

DOM2 HTML (基本上已经过时,请参阅 HTML spec) DOM2 Core (已过时) DOM3 Core (已过时) DOM4

这些规范有很好的索引,我建议将它们的链接放在手边;我一直在使用它们。

自定义属性将包括,例如,任何data-xyz 属性,您可能会添加到元素上以向您的代码提供元数据(现在从 HTML5 开始有效,只要您坚持使用 data- 前缀) . (最新版本的 jQuery 让您可以通过 data 函数访问 data-xyz 元素,但该函数只是 data-xyz 属性的访问器 [它的作用不止于此] ; 除非你真的需要它的特性,否则我会使用attr 函数与data-xyz 属性进行交互。)

attr 函数曾经有一些复杂的逻辑来获取他们认为你想要的东西,而不是从字面上获取属性。它混淆了这些概念。移动到propattr 是为了消除它们的混淆。简而言之,在 v1.6.0 中,jQuery 在这方面做得太过分了,但功能 was quickly added back 到 attr 可以处理人们在技术上应该使用 prop 时使用 attr 的常见情况。

【讨论】:

【参考方案5】:

只是 HTML 属性和 DOM 对象之间的区别会引起混淆。对于那些对 DOM 元素原生属性(如 this.src this.value this.checked 等)进行操作的人来说,.prop 是一个非常热烈的欢迎家庭。对于其他人来说,这只是增加了一层混乱。让我们澄清一下。

查看.attr.prop 之间区别的最简单方法是以下示例:

<input blah="hello">
    $('input').attr('blah'):按预期返回'hello'。这里没有惊喜。 $('input').prop('blah'):返回undefined——因为它正在尝试做[HTMLInputElement].blah——并且该DOM对象不存在这样的属性。它仅作为该元素的属性存在于范围内,即[HTMLInputElement].getAttribute('blah')

现在我们像这样改变一些东西:

$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');
    $('input').attr('blah'):返回'apple' 嗯?为什么不使用“梨”,因为这是在该元素上最后设置的。因为属性是在 input 属性上改变的,而不是 DOM 输入元素本身——它们基本上几乎是相互独立工作的。 $('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')

【讨论】:

【参考方案6】:

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

更多细节

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

示例:更改标签的class 属性将更改DOM 中该标签的className 属性(这是因为class 已被使用)。 如果标签上没有属性,则仍然有相应的 DOM 属性,其值为空或默认值。

示例:虽然您的标签没有 class 属性,但 DOM 属性 className 确实存在,但字符串值为空。

编辑

如果您更改一个,另一个将由控制器更改,反之亦然。 这个控制器不在 jQuery 中,而是在浏览器的原生代码中。

【讨论】:

【参考方案7】:

通常你会想要使用属性。 仅将属性用于:

    获取自定义 HTML 属性(因为它没有与 DOM 属性同步)。 获取不与 DOM 属性同步的 HTML 属性,例如获取标准 HTML 属性的“原始值”,例如 &lt;input value="abc"&gt;.

【讨论】:

【参考方案8】:

脏检查

这个概念提供了一个可以观察到差异的示例: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" 内容属性不再切换检查性强>。

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

【讨论】:

【参考方案9】:

TL;DR

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

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

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

【讨论】:

如果可能的话,附上一些简单的例子来说明你所说的话,并说明何时使用prop() and when to go for attr()。等待答案:)【参考方案10】:

attributes -> HTML

properties -> DOM

【讨论】:

我知道你想说什么,但 HTML 是一种标记语言,而 DOM 是由 HTML 创建的表示。一个 DOMElement 同时具有 attributesproperties【参考方案11】:

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

重要的是,它们中的许多都是同步的(如果您更新 class 属性,则 html 中的 class 属性也将被更新;否则)。 但是某些属性可能会同步到意外的属性 - 例如,attribute checked 对应于 property 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() 官方建议后者?

    .prop() 可以返回任何类型——字符串、整数、布尔值;而.attr() 总是返回一个字符串。 .prop() 据说比 .attr() 快 2.5 倍。

【讨论】:

【参考方案12】:

如果代码以这种方式编写,Gary Hole 的答案与解决问题非常相关

obj.prop("style","border:1px red solid;")

由于 prop 函数返回 CSSStyleDeclaration 对象,上述代码在某些浏览器中将无法正常工作(在我的情况下使用 IE8 with Chrome Frame Plugin 测试)。

因此将其更改为以下代码

obj.prop("style").cssText = "border:1px red solid;"

解决了问题。

【讨论】:

【参考方案13】:

温馨提示使用prop(),例如:

if ($("#checkbox1").prop('checked')) 
    isDelete = 1;
 else 
    isDelete = 0;

上面的函数用来检查checkbox1是否被选中,如果选中:return 1;如果不是:返回 0。函数 prop() 在这里用作 GET 函数。

if ($("#checkbox1").prop('checked', true)) 
    isDelete = 1;
 else 
    isDelete = 0;

上面的函数用来设置checkbox1被选中并且总是返回1。现在函数prop()用作SET函数。

别搞砸了。

P/S:当我检查 Image src 属性时。如果src为空,prop返回页面的当前URL(错误),attr返回空字符串(右)。

【讨论】:

【参考方案14】:

在 jQuery 1.6 之前,attr() 方法有时 在检索属性时会考虑属性值,这会导致相当不一致的行为。

prop() 方法的引入提供了一种显式检索属性值的方法,而 .attr() 检索属性。

文档:

jQuery.attr() 获取匹配元素集中第一个元素的属性值。

jQuery.prop() 获取匹配元素集中第一个元素的属性值。

【讨论】:

【参考方案15】:

.attr():

获取匹配元素集中第一个元素的属性值。 在页面加载时为您提供在 html 中定义的元素值

.prop():

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

【讨论】:

【参考方案16】:

1) 一个属性在 DOM 中;一个属性在 HTML 中是 解析成 DOM。

2) $( elem ).attr( "checked" ) (1.6.1+) "checked" (String) 将 随复选框状态变化

3) $( elem ).attr( "checked" ) (pre-1.6) true (Boolean) Changed 带有复选框状态

大多数情况下,我们希望用于 DOM 对象而不是自定义属性 喜欢data-img, data-xyz

在访问checkbox 值和href 时也存在一些差异 attr()prop() 随着 DOM 输出的变化而变化 prop() 作为来自 originBoolean 复选框值的完整链接 (pre-1.6)

我们只能使用 prop 访问 DOM 元素,否则它会提供 undefined

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>prop demo</title>
  <style>
    p 
      margin: 20px 0 0;
    
    b 
      color: blue;
    
  </style>

</head>

<body>

  <input id="check1" type="checkbox" checked="checked">
  <label for="check1">Check me</label>
  <p></p>

  <script>
    $("input").change(function() 
      var $input = $(this);
      $("p").html(
        ".attr( \"checked\" ): <b>" + $input.attr("checked") + "</b><br>" +
        ".prop( \"checked\" ): <b>" + $input.prop("checked") + "</b><br>" +
        ".is( \":checked\" ): <b>" + $input.is(":checked")) + "</b>";
    ).change();
  </script>

</body>

</html>

【讨论】:

【参考方案17】:

.attr() 可以做到 .prop() 不能做到的一件事:影响 CSS 选择器

这是我在其他答案中没有看到的问题。

CSS 选择器[name=value]

将回复.attr('name', 'value') 但不总是.prop('name', 'value')

.prop() 只影响少数属性选择器

input[name](感谢@TimDown)

.attr() 影响所有属性选择器

input[value] input[naame] span[name] input[data-custom-attribute].data('custom-attribute') 也不会影响此选择器)

【讨论】:

最后,有人在谈论使用attrprop 设置属性及其值。每个人都在谈论这两种方法的get 用法,我找不到我要找的东西。感谢您添加此内容。【参考方案18】:

在 prop() 与 attr() 中还有一些注意事项:

应使用 .prop() 方法检索和设置 selectedIndex、tagName、nodeName、nodeType、ownerDocument、defaultChecked 和 defaultSelected..等。这些没有对应的属性,只是属性。

对于输入类型复选框

   .attr('checked') //returns  checked
   .prop('checked') //returns  true
   .is(':checked') //returns true

prop 方法返回选中、选中、禁用的布尔值, readOnly..etc 而 attr 返回定义的字符串。所以,你可以直接 在 if 条件下使用 .prop('checked')。

.attr() 在内部调用 .prop() 所以 .attr() 方法会稍微 比直接通过 .prop() 访问它们要慢。

【讨论】:

我有 49% 的把握 attr 方法确实在内部调用 prop

以上是关于.prop() 与 .attr()的主要内容,如果未能解决你的问题,请参考以下文章

prop与attr的区别

jquery attr与prop的区别

jq中.prop()与attr()的区别

JQuery中Attr与Prop的区别

JQuery之Attr()与Prop()方法

jq的attr()与prop()之间区别