HTML中属性(Properties)和特性(Attributes)有什么区别?

585
自从jQuery 1.6.1版本进行了更改后,我一直在尝试定义HTML中属性和特性之间的区别。通过查看jQuery 1.6.1版本的发行说明列表(位于底部附近)(链接),似乎可以将HTML属性和特性分类如下:
  • 属性:所有具有布尔值或UA计算值(例如selectedIndex)的属性。

  • 特性:可添加到HTML元素中的“特性”,既不是布尔值,也不包含UA生成的值。

思考一下?

6
可能是.prop() vs .attr()的重复问题。 - Naftali
8个回答

1167
在编写 HTML 源代码时,您可以在 HTML 元素上定义属性。然后,一旦浏览器解析您的代码,相应的 DOM 节点将被创建。该节点是一个对象,因此它具有属性。
例如,这个 HTML 元素:
<input type="text" value="Name:">

有 2 个属性(typevalue)。

一旦浏览器解析此代码,将创建一个 HTMLInputElement 对象,并且该对象将包含许多属性,例如:accept、accessKey、align、alt、attributes、autofocus、baseURI、checked、childElementCount、childNodes、children、classList、className、clientHeight 等等。

对于给定的 DOM 节点对象,属性是该对象的属性,而属性是该对象的 attributes 属性中的元素。

当为给定的 HTML 元素创建 DOM 节点时,其许多属性与具有相同或类似名称的属性相关联,但这不是一对一的关系。例如,对于此 HTML 元素:

<input id="the-input" type="text" value="Name:">

对应的DOM节点将具有idtypevalue属性(以及其他属性):

  • id属性是id属性的反射属性:获取属性会读取属性值,设置属性会写入属性值。id是一个纯的反射属性,它不会修改或限制该值。

  • type属性是type属性的反射属性:获取属性会读取属性值,设置属性会写入属性值。type不是一个纯的反射属性,因为它受限于已知值(例如输入的有效类型)。如果您有 <input type="foo">,那么 theInput.getAttribute("type") 将给出 "foo",但 theInput.type 将给出 "text"

  • 相比之下,value属性不反映value属性。相反,它是输入框的当前值。当用户手动更改输入框的值时,value属性将反映此更改。因此,如果用户在输入框中输入“John”,则:

    theInput.value // returns "John"
    

    而:

    theInput.getAttribute('value') // returns "Name:"
    

    value属性反映了输入框中当前的文本内容,而value属性包含来自HTML源代码的初始文本内容。

    因此,如果您想知道文本框中当前的内容,读取属性。但是,如果您想知道文本框的初始值是什么,请读取属性。或者,您可以使用defaultValue属性,它完全反映了value属性:

    theInput.value                 // returns "John"
    theInput.getAttribute('value') // returns "Name:"
    theInput.defaultValue          // returns "Name:"
    
    有一些属性直接反映它们的特性(relid),有一些则是具有稍微不同名称的直接反映(htmlFor 反映 for 特性,className 反映 class 特性),许多属性反映了它们的特性但具有限制/修改(srchrefdisabledmultiple),等等。在规范中涵盖了各种类型的反射。

1
嘿Sime,我猜这个可能相当模糊,特别是如果你在这里看一下:http://www.w3.org/TR/html4/index/attributes.html,并且没有明确的答案。基本上需要遵循jQuery博客中总结的内容,即使如此,一个会映射到另一个,并在两种情况下都能工作,但如果你错误地使用prop而不是attr,性能会稍微受到影响。 - schalkneethling
7
@oss你的链接指的是HTML属性列表。该列表并不含糊,那些都是属性。 - Šime Vidas
3
我在哪里可以找到属性到属性(例如 for -> htmlFor)的完整列表,以及类似地从属性中获取其初始值但不反映它的属性的列表(input.value)?我希望这些信息可以在像 https://github.com/Matt-Esch/virtual-dom 这样的库源代码中找到,但实际上并没有详细记录。 - sstur
1
很好的解释,但你没有提到setAttribute以及在没有初始设置属性时它是如何工作的。<input type="text"/>没有value属性,但是getAttribute('value')input.value都将返回空字符串。此外,setAttribute('value', newVal')(以及随后的调用)将同时更改属性和value/defaultValue属性。但是,如果您现在将input.value设置为空字符串(已经是),随后的setAttribute调用将仅影响属性和defaultValue属性,而value属性保持不变。 - cimak
1
@Pim 我自己还没有阅读过,但这个由4部分组成的文章系列似乎是一个很好的资源:https://twitter.com/addyosmani/status/1082177515618295808 - Šime Vidas
显示剩余8条评论

126

阅读了Sime Vidas的回答后,我进行了更多搜索,并在angular文档中找到了一个非常直观且易于理解的解释。

HTML属性与DOM属性


属性由HTML定义。属性由DOM(文档对象模型)定义。 一些HTML属性具有1:1映射到属性。 id是一个例子。 一些HTML属性没有相应的属性。 colspan是一个例子。 一些DOM属性没有相应的属性。 textContent是一个例子。 许多HTML属性似乎映射到属性...但不是你想象的那样! 直到你掌握了这个通用规则,最后一个类别才会令人困惑: 属性初始化DOM属性,然后它们就完成了。属性值可以更改;属性值不能更改。 例如,当浏览器呈现时,它创建一个相应的DOM节点,并将value属性初始化为“Bob”。 当用户在输入框中输入“Sally”时,DOM元素的value属性变为“Sally”。但是,如果您询问输入元素该属性,则HTML value属性保持不变:input.getAttribute('value')返回“Bob”。 HTML属性value指定初始值; DOM value属性是当前值。

disabled 属性是另一个奇特的例子。按钮的 disabled 属性默认为 false,因此按钮是启用状态。当您添加 disabled 属性时,仅其存在就会将按钮的 disabled 属性初始化为 true,从而禁用按钮。

添加和删除 disabled 属性将禁用和启用按钮。属性的值是无关紧要的,这就是为什么不能通过编写 <button disabled="false">Still Disabled</button> 来启用按钮的原因。

设置按钮的 disabled 属性 可以禁用或启用按钮。 属性 的值很重要。

即使名称相同,HTML 属性和 DOM 属性也不是同一回事。


这个例子不正确:colspan 属性应该是 colSpan 属性。那么,现在哪个属性没有对应的属性呢? - Robert Siemer

51
答案已经解释了属性和属性值的处理方式不同,但我真的想强调这是多么疯狂。即使在某种程度上是规范要求如此。
这是荒谬的,有些属性(例如id、class、foo、bar)只保留DOM中的一种值,而有些属性(例如checked、selected)则保留两个值;也就是说,"加载时"的值和"动态状态"的值。(难道DOM不应该完全反映文档的状态吗?)
非常重要的是,两个输入字段,例如文本和复选框,必须以完全相同的方式进行操作。如果文本输入字段不保留单独的"加载时"值和"当前、动态"值,为什么复选框会有呢?如果复选框的checked属性有两个值,为什么它的class和id属性没有呢? 如果你希望改变文本输入字段的值,并期望DOM(即"序列化表示")发生改变并反映这种改变,那么为什么你不期望同样的事情发生在type为checkbox的input字段上的checked属性上呢?
对于"它是一个布尔属性"的区分,我完全看不懂,或者至少不足以成为这样做的充分理由。

24
这不是一个答案,但我同意你的看法;这完全是疯了。 - Samuel
55
不是疯狂的。你误解了。checked属性由defaultChecked属性表示(类似于文本输入的value属性由defaultValue属性表示)。需要第二个属性checked来表示复选框是否被选中,因为这是复选框功能的固有部分:它是交互式的,并且可以通过用户进行更改(如果存在表单重置按钮,则可以将其重置为默认值),这与其他属性,例如id不同。这与它是布尔属性无关。 - Tim Down
3
@TimDown -- 谢谢。实际上,这让我跨过了困惑的难关。 - pedz
14
我认为这仍然是“疯狂的”,因为任何逻辑方法都应使属性名称和属性名匹配,或至少不要让没有关系的属性名称和属性名匹配(即checked属性引用defaultChecked属性而checked属性无关)。事实上,每个人最初假定的逻辑方法是根本不区分属性和属性值。属性不应该是不可变的,而应始终反映属性值。两者之间不应有区别。 - dallin
3
如果你理解为什么要这样制作,那么它就不是荒谬的。它之所以这样做是因为“表单”有一个重置方法,而该重置方法需要从HTML属性中读取原始数据。 - Ahmad Alfy
显示剩余3条评论

19

HTML属性和特性的区别:

在评估HTML中的区别之前,我们先来看一下这些单词的定义:

英文定义:

  • 属性是指对象的附加信息。
  • 特性描述了对象的特性。

在HTML上下文中:

当浏览器解析HTML时,它会创建一个树形数据结构,基本上是HTML在内存中的表示。树形数据结构包含的节点是HTML元素和文本。属性和特性与其关系如下:

  • 属性是我们可以在HTML中添加的附加信息,用于初始化某些DOM特性。
  • 特性是在浏览器解析HTML并生成DOM时形成的。DOM中的每个元素都有自己的一组属性,这些属性都由浏览器设置。其中某些属性的初始值可以通过HTML属性设置。每当影响呈现页面的DOM属性发生更改时,页面将立即重新呈现

此外,重要的是要意识到这些属性的映射不是1对1的。换句话说,我们在HTML元素上给出的每个属性都不一定会有相似命名的DOM属性。

此外,不同的DOM元素具有不同的属性。例如,<input> 元素具有一个值属性,而 <div> 元素上没有该属性。

示例:

让我们看下面的HTML文档:

 <!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">  <!-- charset is a attribute -->
  <meta name="viewport" content="width=device-width"> <!-- name and content are attributes -->
  <title>JS Bin</title>
</head>
<body>
<div id="foo" class="bar foobar">hi</div> <!-- id and class are attributes -->
</body>
</html>

然后我们在JS控制台中检查<div>

 console.dir(document.getElementById('foo'));

我们看到以下DOM属性(chrome开发者工具,不显示所有属性):

html属性和特性

  • 我们可以看到HTML中的id属性现在也是DOM中的id属性。 id已经由HTML初始化(虽然我们可以用javascript更改它)。
  • 我们可以看到HTML中的类属性没有相应的类属性(class 是JS中的保留关键字)。但实际上有2个属性:classListclassName

2
这个答案非常好,因为它展示了_例子_,没有这些例子,属性和特性之间的区别很容易被忽略。 - ProfDFrancis

11

这些都是由W3C指定的,属性和属性有什么区别呢? http://www.w3.org/TR/SVGTiny12/attributeTable.html

但目前attr和prop并没有太大的区别,它们几乎相同

但他们更喜欢用prop来处理某些事情

首选用法摘要

.prop()方法应该用于布尔属性/属性以及在html中不存在的属性(例如window.location)。所有其他属性(您可以在html中看到的属性)都可以和应该继续使用.attr()方法进行操作。

实际上,如果您同时使用attr或prop,您不必更改任何内容,两者都可以正常工作。但我在自己的应用程序中发现,当attr无法正常工作时,prop可以正常工作,因此我在我的1.6应用程序中采用了prop =)


嗨,丹尼尔,我看过了那个。只是似乎没有明确的定义来区分这两者,因为Sime在下面提到的一些内容也可以添加到HTML元素中,例如alt属性。将会继续阅读一些HTML规范并查看是否确实有一种方法来在实践中清楚地区分这两者。 - schalkneethling
5
这份文件涉及到的是SVG而不是HTML。 - Luzado

5

我的回答更新,引用自https://angular.io/guide/binding-syntax

HTML属性和DOM属性

属性初始化DOM属性,您可以配置它们来修改元素的行为,但属性是DOM节点的特性。

  • 一些HTML属性与属性具有1:1映射;例如,id。

  • 某些HTML属性没有相应的属性;例如,aria-*。

  • 某些DOM属性没有相应的属性;例如,textContent。

请记住,即使它们具有相同的名称,HTML属性和DOM属性也是不同的东西。

示例1:当浏览器呈现<input value="Sarah">时,它将创建一个相应的DOM节点,并初始化该值属性为"Sarah"。

<input type="text" value="Sarah">

当用户输入“Sally”到元素时,DOM元素的value属性变成了Sally。然而,如果你使用input.getAttribute('value')查看HTML属性的值,你会发现该属性保持不变,仍然返回"Sarah"。
HTML属性"value"指定了初始值;而DOM中的"value"属性则是当前值。
示例2: 禁用按钮 按钮的disabled属性默认为false,因此按钮是启用状态。 当你添加了disabled属性时,你将按钮的disabled属性初始化为true,从而禁用了按钮。
<button disabled>Test Button</button>

添加和移除"disabled"属性可以禁用和启用按钮。但是,该属性的值是无关紧要的,因此您不能通过写"Still Disabled"来启用按钮。

要控制按钮的状态,请设置"disabled"属性。

属性和属性绑定的比较 尽管您可以在技术上设置[attr.disabled]属性绑定,但它们的值不同,属性绑定必须是布尔值,而其对应的属性绑定则取决于该值是否为null。请考虑以下内容:

<input [disabled]="condition ? true : false">
<input [attr.disabled]="condition ? 'disabled' : null">

第一行使用了禁用属性,它使用了布尔值。第二行则检查null使用了禁用属性。

通常情况下,使用属性绑定比使用属性绑定更好,因为布尔值更容易阅读,语法更简洁,属性的性能更高。


1
这部分内容部分来自www.coursehero.com。如果你复制粘贴答案,请让人们知道原始答案的来源。 - B001ᛦ
1
哇!如果我没有看到你的评论,我会认为这个答案真的很好。谢谢 :) - Vijay Dev
1
抱歉,大家,我忘了提到答案来源于 https://angular.io/guide/binding-syntax。 - mkamal

2

属性:属性由HTML定义,并用于自定义标签。

属性:HTML DOM属性是您可以设置或更改的值(HTML元素的值)。

因此,属性和属性之间的主要区别是:

  • 属性由HTML定义,而属性由DOM定义。

  • 属性的主要作用是初始化DOM属性。因此,一旦DOM初始化完成,属性的工作就完成了。


属性不是常量,它们可以在许多情况下进行更新,例如 inputElement.setAttribute('maxlength', 2) - Drenai
属性并非固定不变的,它们在许多情况下可以被更新,例如 inputElement.setAttribute('maxlength', 2) - Drenai
1
在某些情况下,初始化后需要使用属性而不是prop。如果您有一个HTML进度条,它被初始化为特定值,但后来您想将其更改为不确定状态,则唯一的方法是使用removeAttribute,使用.value = null会重置为0,但不会强制进入不确定状态。简而言之,事情并不总是非黑即白。 - Mâtt Frëëman

0

属性初始化DOM属性,您可以配置它们来修改元素的行为。 属性是DOM节点的特性。

  • 一些HTML属性与属性具有1:1的映射关系;例如

    id

  • 一些HTML属性没有对应的属性;例如

    aria-*

  • 一些DOM属性没有对应的属性;例如

    textContent

请记住,HTML属性和DOM属性是不同的东西,即使它们具有相同的名称。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接