.prop() 与 .attr()

IT技术 javascript jquery dom attr prop
2021-01-01 16:08:06

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

6个回答

2012 年 11 月 1 日更新

我的原始答案专门适用于 jQuery 1.6。我的建议保持不变,但 jQuery 1.6.1 稍微改变了一些:面对预测的一堆损坏的网站,jQuery 团队恢复attr()到接近(但不完全相同)其旧行为的 Boolean 属性John Resig 也写了关于它的博客我可以看到他们遇到的困难,但仍然不同意他的建议attr()

原答案

如果您只使用过 jQuery 而不是直接使用 DOM,这可能是一个令人困惑的更改,尽管它在概念上绝对是一个改进。不过,对于使用 jQuery 的无数站点来说,这并不是那么好,这些站点将由于此更改而中断。

我总结一下主要问题:

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

如果您是 jQuery 开发人员,并且对属性和属性的整个业务感到困惑,那么您需要退后一步,了解一下它,因为 jQuery 不再那么努力地保护您免受这些东西的影响。对于这个主题的权威但有点枯燥的词,有规范:DOM4HTML DOMDOM Level 2DOM Level 3Mozilla 的 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") ) {...}

这实际上是世界上使用checkedBoolean 属性做的最简单的事情,自 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 对象中的单独属性映射中。在大多数情况下,写入 prop 只会改变 prop,虽然遗憾的是有一些 props 将任何更改写入底层 attr(value例如),但让我们尽量忽略它。99% 的情况下,您想要使用道具。如果您需要使用实际属性,您可能会知道这一点。
2021-02-22 16:08:06

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

DOM 元素是一个对象,是内存中的一个东西。像 OOP 中的大多数对象一样,它具有属性它还单独具有元素上定义的属性的映射(通常来自浏览器读取以创建元素的标记)。有些元素的属性得到他们最初从值属性具有相同或相似名称(value从“值”属性获取其初始值;href从“href”属性获取其初始值,但它不是完全一样的值;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" |
| 名称: "fooAnchor" |
| id: "fooAnchor" |
| className: "测试一" |
| 属性: |
| 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 规范中列出:

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

例如,自定义属性将包括data-xyz您可能放在元素上以向代码提供元数据的任何属性(现在,只要您坚持使用data-前缀,这从 HTML5 开始就有效)。(jQuery的的最新版本给你访问data-xyz通过要素data的功能,但该功能是不是只是一个访问data-xyz属性[它都越来越小于];除非你真正需要它的特点,我会使用的attr功能互动带data-xyz属性。)

attr函数曾经有一些复杂的逻辑来获取他们认为你想要的东西,而不是从字面上获取属性。它混淆了概念。移动到prop并且attr旨在消除它们的混淆。简要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 属性 类属性显示在主体的此处。可以通过以下代码访问:

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 属性的作用。请注意,attributes 与 properties 完全不同,因为此事件处理程序分配是无用的并且不会接收事件(body 没有 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 属性之间的差异有关,而不是与代码本身有关。希望这为您解决了一些问题。

-马特

哥们,我现在也很迷茫。所以$('#test').prop('value')不返回任何东西?也不.attr('checked')是复选框?但它曾经?现在你必须把它改成prop('checked')? 我不明白这种区别的必要性 - 为什么区分 HTML 属性和 DOM 属性很重要?使此更改“很长时间”的常见用例是什么?抽象出两者之间的区别有什么问题,因为它们的用例似乎大多重叠?
2021-02-07 16:08:06
$.prop()获取 DOM 属性,$.attr()获取 HTML 属性。我试图在心理上弥合差距,以便您了解两者之间的区别。
2021-02-20 16:08:06

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

更多细节

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

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

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

编辑

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

导致混淆的只是 HTML 属性和 DOM 对象之间的区别。对于那些习惯于处理 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'吗?为什么不“梨”,因为它最后设置在该元素上。因为属性是在 input 属性上更改的,而不是 DOM 输入元素本身——它们基本上彼此独立工作。
  2. $('input').prop('blah'): 返回 'pear'

由于上述原因,您真正需要注意的是不要在整个应用程序中混合使用这些相同的属性

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


.attr对比.prop

第一轮:风格

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

第二轮:value

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