. prop()vs. attr()

所以jQuery 1.6有了新函数#0

$(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,为什么?这对我将来的编码有什么影响?

702636 次浏览

一切都在该医生

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

使用Prop!

这种变化对于jQuery来说已经有很长时间了。多年来,他们一直满足于一个名为attr()的函数,该函数主要检索DOM属性,而不是您期望的名称结果。#0#2的分离应该有助于减轻超文本标记语言属性和DOM属性之间的一些混淆。$.fn.prop()抓取指定的DOM属性,而$.fn.attr()抓取指定的超文本标记语言属性。

为了充分理解它们是如何工作的,这里对超文本标记语言属性和DOM属性之间的区别进行了扩展解释:

超文本标记语言属性

语法:

<body onload="foo()">

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

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

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

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

DOM属性

语法:

document.body.onload = foo;

<强>目的:提供对属于元素节点的属性的访问。这些属性类似于属性,但只能通过JavaScript访问。这是一个重要的区别,有助于澄清DOM属性的作用。请注意,属性与属性完全不同,因为这个事件处理程序分配是无用的,不会接收事件(body没有onload事件,只有onload属性)。

可视化:DOM属性

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

需求文档

示例

超文本标记语言:<textarea id="test" value="foo"></textarea>

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

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

在没有看过这两个函数的新代码的情况下,我可以自信地说,混淆更多的是与超文本标记语言属性和DOM属性之间的差异有关,而不是与代码本身有关。

马特

2012年11月1日更新

我最初的回答特别适用于jQuery 1.6。我的建议保持不变,但jQuery 1.6.1略有改变:面对预测的一堆破碎的网站,jQuery团队将#0恢复为接近(但不完全相同)其布尔属性的旧行为。John Resig也是关于它的博客。我可以看到他们遇到的困难,但仍然不同意他的建议,宁愿选择attr()

原答复

如果你只使用过jQuery而不是直接使用DOM,这可能是一个令人困惑的变化,尽管它在概念上绝对是一个改进。

我将总结主要问题:

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

如果你是一名jQuery开发人员,并且对有关属性和属性的整个业务感到困惑,那么你需要退后一步并了解一点,因为jQuery不再努力保护你免受这些东西的影响。对于这个主题的权威但有点枯燥的词,有规格:DOM4超文本标记语言DOMDOM级别2DOM级别3。Mozilla的DOM留档对大多数现代浏览器都有效,并且比规格更易于阅读,因此您可能会发现它们的DOM参考很有帮助。有一个元素属性部分

作为一个属性比属性更容易处理的例子,考虑一个最初被选中的复选框。这里有两个可能的有效超文本标记语言来做到这一点:

<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/

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

DOM元素是一个对象,一个内存中的东西。像OOP中的大多数对象一样,它有属性。另外,它还有一个定义在元素上的属性映射(通常来自浏览器为创建元素而读取的标记)。一些元素的属性属性获得它们的初始值,名称相同或相似(value从“value”属性获得初始值;href从“href”属性获得初始值,但它不是完全相同的值;className从“class”属性)。其他属性以其他方式获得初始值:例如,parentNode属性根据其父元素是什么获取其值;元素始终具有style属性,无论它是否具有“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-前缀)。(jQuery的最新版本允许您通过data函数访问data-xyz元素,但该函数没有只是data-xyz属性的访问器[它做的更多和更少];除非您确实需要它的功能,否则我会使用attr函数与data-xyz属性交互。)

attr函数曾经有一些复杂的逻辑来获取他们认为你想要的东西,而不是从字面上获取属性。它混淆了概念。移动到propattr是为了消除它们的冲突。在v1.6.0中,jQuery在这方面走得太远了,但是功能很快又加了回来attr来处理人们在技术上应该使用prop时使用attr的常见情况。

只是超文本标记语言属性和DOM对象之间的区别导致了混乱。对于那些习惯于处理DOM元素本机属性(如this.srcthis.valuethis.checked等)的人来说,.prop是一个非常热烈的欢迎。对于其他人来说,这只是增加了一层混乱。让我们把它弄清楚。

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

<input blah="hello">
  1. #0:按预期返回'hello'。这里没有惊喜。
  2. #0:返回undefined-因为它试图做[HTMLInputElement].blah-并且该DOM对象上不存在这样的属性。它只作为该元素的属性存在于范围内,即[HTMLInputElement].getAttribute('blah')

现在我们改变几件事情像这样:

$('input').attr('blah', 'apple');$('input').prop('blah', 'pear');
  1. #0:返回'apple'嗯?为什么不“pear”,因为这是在该元素上最后设置的。因为属性是在输入属性上更改的,而不是DOM输入元素本身——它们基本上几乎是相互独立工作的。
  2. #0:返回'pear'

由于上述原因,你真正需要小心的事情只是不要在整个应用程序中对相同的属性混合使用这些属性

看一个小提琴演示差异:http://jsfiddle.net/garreh/uLQXc/


.attr vs.prop

第1轮:风格

<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')

属性位于DOM中;属性位于解析到DOM中的超文本标记语言中。

更多细节

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

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

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

编辑

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

通常你会想要使用属性。仅对以下对象使用属性:

  1. 获取自定义超文本标记语言属性(因为它没有与DOM属性同步)。
  2. 获取不与DOM属性同步的超文本标记语言属性,例如获取标准超文本标记语言属性的“原始值”,如<input value="abc">.

肮脏的检查

这个概念提供了一个可以观察到差异的示例: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属性必须反映禁用的内容属性。

所以你可能会逃脱惩罚,尽管它很丑陋,因为它不需要修改超文本标记语言。

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

这就是为什么你应该主要使用.prop,因为它直接影响有效属性,而不是依赖于修改超文本标记语言的复杂副作用。

太长别读

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

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

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

attributes->超文本标记语言

properties->DOM

属性是您的超文本标记语言文本文件(==假设这是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倍。

Gary Hole的回答与解决问题非常相关如果代码是这样写的

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

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

从而将其更改为以下代码

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

解决了问题。

轻轻提醒使用prop(),例如:

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

上面的函数用于检查复选框1是否被选中,如果被选中:返回1;如果没有:返回0。这里用作GET函数的函数prop()。

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

上面的函数用于设置复选框1被选中并始终返回1。现在函数prop()用作SET函数。

别搞砸了。

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

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

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

文档:

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

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

.attr()

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

.prop()

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

1)属性在DOM中;属性在超文本标记语言中解析到DOM中。

2)$(elem). attr(“已检查”)(1.6.1+)“已检查”(String)Will更改复选框状态

3)$(elem). attr(“已检查”)(pre-1.6)true(Boolean)更改复选框状态

  • 大多数情况下,我们希望使用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>

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

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

CSS选择器[name=value]

  • 将响应.attr('name', 'value')
  • 但不总是.prop('name', 'value')

.prop()只影响几个属性选择器

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

在prop()与attr()中还有一些考虑因素:

  • selectedIndex、tagName、nodeName、nodeType、ownerDocument、defaultChecked和defaultS选择… etc应该使用. prop()方法检索和设置。这些没有相应的属性,只是属性。

  • 输入类型复选框

       .attr('checked') //returns  checked.prop('checked') //returns  true.is(':checked') //returns true
  • prop method returns Boolean value for checked, selected, disabled,readOnly..etc while attr returns defined string. So, you can directlyuse .prop(‘checked’) in if condition.

  • .attr() calls .prop() internally so .attr() method will be slightlyslower than accessing them directly through .prop().