引言
之前在阅读vue
的api
的时候,在解释指令v-bind
时,其中关于修饰符 .prop
的解释是- 作为一个 DOM property 绑定而不是作为 attribute 绑定。 令我挺好奇的,虽然干了这么久前端还未详细探究过两者之前的具体区别。于是就跟着链接进入了Stack Overflow中,看与这相关的一个问题与讨论。讨论的内容也经多位牛人编辑,总结得很详细,就想着把这里面的内容在博客中分享记录一下。奈何时间关系,一直在博客的草稿箱里,年底了不怎么忙,趁有时间就总结翻译一下。
明确概念
首先因为两个单词在中文中都翻译成属性,所以会造成较多混淆。在此也先明确一下其它一些基础概念。
身为前端人员我们经常会用标签
,元素
,DOM
来形容HTML
内容,对此其实有明确划分的。如下HTML code
(能明确区分的可以跳过)
<div id="" class=""></div>
标签指的是 div
,也有其他标签如:a
,p
,input
等等。
多数标签分为<div>
开始标签(opening tag),以及</div>
结束标签(closing tag)。
当然有的也不区分如: <input>
,<hr>
,<br>
等。
标签上有附加信息我们称之为 HTML 属性
,如 id
,class
以上合起来,我们统称为HTML 元素
,而一个HTML文档
就是多个HTML元素
构成的。
而HTML DOM
是 HTML 的标准对象模型,DOM(Document Object Model)
,直译就是文档对象模型
HTML DOM
定义了所有 HTML 元素的对象和属性,以及访问它们的方法。
而DOM对象上的属性我们称之为property
。
讨论原因
引发此次讨论的主要原因就是因为jQuery v1.6.1
的发布,此版本之前直接用attr()
方法处理了property
和attribute
,为了消除property
和attribute
的歧义,以及一些attr()
的bug和维护困难的问题,于是新添加了prop()
方法,jQuery v1.6.1
发布日志可以在这里看。
详细解释
编写HTML源代码时,可以在HTML元素上定义属性(attribute) 。 然后,一旦浏览器解析了您的代码,就会创建一个对应的DOM节点。 该节点是一个对象,因此具有属性 (property)。 例如:
<input type="text" value="name">
input
元素有两个属性(attribute),type
和value
。
浏览器解析这段代码后,将创建一个HTMLInputElement对象,该对象将包含许多属性。
例如:accept
,accessKey
,align
,alt
,attributes
,autofocus
,baseURI
,checked
,childElementCount
,childNodes
,childNodes
,classList
,className
,clientHeight
等
解析创建后的这个DOM节点对象,property
是这个对象的属性,而attribute
是这个对象的attributes
这个对象的属性
(简单讲就是这样 domObj.attibutes.attribute
)。
因为是根据HTML 元素创建的DOM节点对象,所以会有许多属性(property)都与具有相同或相似名称的属性(attribute)相关,但这不并是一对一的关系。 比如:
<input id="inputId" type="text" value="name">
此元素创建的DOM节点对象有,id
,type
,value
等属性(property)
DOM节点对象上的id
属性(property)是映射的id
属性(attribute)。获取id
的property
就是获取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
不是纯粹的映射属性,因为它的值只能为 已知值 (例如:text
,submit
,button
,checkbox
等等)。以下可以看到,设置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
由以上可以得知,input
的value
属性(property)在用户未输入数据,或设置property
的值时,取的值是attribute
的值。当用户输入值或者设置了property
的值后,property
的值就不受attribute
影响了,property
的值就是页面输入框内展示的内容(如下图)
attribute
的值是HTML源代码属性(如下图)
从这个例子中就能很明显看出来property
和attribute
的区别了,当然还有很多属性property
与attribute
之间的映射关系并不相同,比如class attribute
和 className property
、classList property
之间的关系等等。
这里有篇 Angular 的文档,其中也描述了html属性和DOM属性的一些内容,有兴趣的小伙伴们可以进去看看。 Web API 接口参考
总结
最后总的来讲就是 HTML属性 (attribute)和 DOM属性(property),是相互关联的。多数情况attribute
值仅用作初始DOM节点对象使用,而property
更多用于页面交互,很多框架都是在与元素和指令的 property
和事件打交道。
以上描述如有错误欢迎指正,谢谢
参考文档
以上所引用文档都尽量更换为中文文档,原英文文档参考下方。
HTMLInputElement Web APIs HTML attribute vs. DOM property Stack Overflow