协慌网

登录 贡献 社区

.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 将打破?

UPDATE

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为字符串,但将propCSSStyleDeclaration ,为什么?这对我未来的编码有何影响?

答案

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 的旧版本除外)对应于输入的默认值 / checkedness(反映在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 检查了复选框?查看 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 ; 从 “值” 属性获取其初始值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对象是真实的东西,你可以看到有访问它的属性 ,以及访问属性之间的真正的区别。

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

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

这些规格有很好的索引,我建议保持链接方便; 我一直都在使用它们。

例如,自定义属性将包括您可能放置在元素上的任何data-xyz属性,以便为您的代码提供元数据(现在,只要您坚持使用data-前缀,该属性就像 HTML5 一样有效)。 (jQuery 的的最新版本给你访问data-xyz通过要素data的功能,但该功能只是一个访问data-xyz属性 [它都越来越小于]; 除非你真正需要它的功能,我使用attr函数与data-xyz属性进行交互。)

attr函数曾经有一些复杂的逻辑来获得他们想要的东西,而不是字面上得到属性。它混淆了这些概念。转向propattr意味着去除它们。简单地说,在 v1.6.0 中,jQuery 在这方面走得太远了,但是功能很快被添加回 attr来处理人们使用attr的常见情况,技术上他们应该使用prop

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 Mode(及以下)需要 get / set / removeAttribute 中 DOM 属性的名称而不是属性名称。这是了解差异的重要原因之一。

DOM 属性

句法:

document.body.onload = foo;

目的:提供对属于元素节点的属性的访问。这些属性与属性类似,但只能通过 JavaScript 访问。这是一个重要的区别,有助于阐明 DOM 属性的作用。 请注意,属性与属性完全不同 ,因为此事件处理程序分配是无用的,并且不会接收事件(正文没有 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 属性之间的差异有关,而不是与代码本身有关。希望这能为你解决一些问题。

-Matt