DOM property 和 attribute 的区别详解

4,806 阅读5分钟

引言

之前在阅读vueapi的时候,在解释指令v-bind时,其中关于修饰符 .prop 的解释是- 作为一个 DOM property 绑定而不是作为 attribute 绑定。 令我挺好奇的,虽然干了这么久前端还未详细探究过两者之前的具体区别。于是就跟着链接进入了Stack Overflow中,看与这相关的一个问题与讨论。讨论的内容也经多位牛人编辑,总结得很详细,就想着把这里面的内容在博客中分享记录一下。奈何时间关系,一直在博客的草稿箱里,年底了不怎么忙,趁有时间就总结翻译一下。

明确概念

首先因为两个单词在中文中都翻译成属性,所以会造成较多混淆。在此也先明确一下其它一些基础概念。 身为前端人员我们经常会用标签元素DOM来形容HTML 内容,对此其实有明确划分的。如下HTML code(能明确区分的可以跳过)

<div id="" class=""></div>

标签指的是 div,也有其他标签如:apinput等等。 多数标签分为<div> 开始标签(opening tag),以及</div>结束标签(closing tag)。 当然有的也不区分如: <input><hr><br>等。 标签上有附加信息我们称之为 HTML 属性,如 idclass 以上合起来,我们统称为HTML 元素,而一个HTML文档就是多个HTML元素构成的。

HTML DOM是 HTML 的标准对象模型,DOM(Document Object Model),直译就是文档对象模型 HTML DOM 定义了所有 HTML 元素的对象属性,以及访问它们的方法。 而DOM对象上的属性我们称之为property

讨论原因

引发此次讨论的主要原因就是因为jQuery v1.6.1的发布,此版本之前直接用attr()方法处理了propertyattribute,为了消除propertyattribute的歧义,以及一些attr()的bug和维护困难的问题,于是新添加了prop()方法,jQuery v1.6.1发布日志可以在这里看。

详细解释

编写HTML源代码时,可以在HTML元素上定义属性(attribute) 。 然后,一旦浏览器解析了您的代码,就会创建一个对应的DOM节点。 该节点是一个对象,因此具有属性 (property)。 例如:

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

input元素有两个属性(attribute),typevalue。 浏览器解析这段代码后,将创建一个HTMLInputElement对象,该对象将包含许多属性。 例如:acceptaccessKeyalignaltattributesautofocusbaseURIcheckedchildElementCountchildNodeschildNodesclassListclassNameclientHeight

解析创建后的这个DOM节点对象property是这个对象的属性,而attribute是这个对象的attributes这个对象的属性 (简单讲就是这样 domObj.attibutes.attribute )。

因为是根据HTML 元素创建的DOM节点对象,所以会有许多属性(property)都与具有相同或相似名称的属性(attribute)相关,但这不并是一对一的关系。 比如:

<input id="inputId" type="text" value="name">

此元素创建的DOM节点对象有,idtypevalue 等属性(property) DOM节点对象上的id 属性(property)是映射的id属性(attribute)。获取idproperty就是获取attribute值,设置也是一样。

var inputDom = document.querySelector('#inputId')
console.log(inputDom.getAttribute('id'))
console.log(inputDom.id)
// "inputId"
// "inputId"

inputDom.setAttribute('id','inputId2')
console.log(inputDom.getAttribute('id'))
console.log(inputDom.id)
// "inputId2"
// "inputId2"

inputDom.id = 'inputId'
console.log(inputDom.getAttribute('id'))
console.log(inputDom.id)
// "inputId"
// "inputId"

DOM节点对象上的type属性(property)是映射 type的属性(attribute),获取property读取的是attribute值,并且设置property写入的是attribute值。type不是纯粹的映射属性,因为它的值只能为 已知值 (例如:textsubmitbuttoncheckbox等等)。以下可以看到,设置type未知值property始终为text。

var inputDom = document.querySelector('#inputId')
console.log(inputDom.getAttribute('type'))
console.log(inputDom.type)
// text
// text

inputDom.setAttribute('type','007')
console.log(inputDom.getAttribute('type'))
console.log(inputDom.type)
// 007
// text

inputDom.type = '008'
console.log(inputDom.getAttribute('type'))
console.log(inputDom.type)
// 008
// text

value属性(property)不是完全映射value属性(attribute)。 初始状态value属性(property)映射的value属性(attribute), 当用户手动更改输入框的内容时 , value属性(property)将更改为用户输入的信息。

<input id="inputId" type="text" value="name">
var inputDom = document.querySelector('#inputId')
console.log(inputDom.getAttribute('value'))
console.log(inputDom.value)
// name
// name

inputDom.setAttribute('value','007')
console.log(inputDom.getAttribute('value'))
console.log(inputDom.value)
// 007
// 007

inputDom.value = '008'
console.log(inputDom.getAttribute('value'))
console.log(inputDom.value)
// 007
// 008

由以上可以得知,inputvalue属性(property)在用户未输入数据,或设置property的值时,取的值是attribute的值。当用户输入值或者设置了property的值后,property的值就不受attribute影响了,property的值就是页面输入框内展示的内容(如下图)

在这里插入图片描述
attribute的值是HTML源代码属性(如下图)
attribute 的值
从这个例子中就能很明显看出来propertyattribute的区别了,当然还有很多属性propertyattribute之间的映射关系并不相同,比如class attributeclassName propertyclassList property 之间的关系等等。

这里有篇 Angular 的文档,其中也描述了html属性和DOM属性的一些内容,有兴趣的小伙伴们可以进去看看。 Web API 接口参考

总结

最后总的来讲就是 HTML属性 (attribute)和 DOM属性(property),是相互关联的。多数情况attribute值仅用作初始DOM节点对象使用,而property更多用于页面交互,很多框架都是在与元素和指令的 property和事件打交道。

以上描述如有错误欢迎指正,谢谢

参考文档

以上所引用文档都尽量更换为中文文档,原英文文档参考下方。

HTMLInputElement Web APIs HTML attribute vs. DOM property Stack Overflow