DOM property 和HTML attribute 的区别详解
引言
今天阅读了vue 的动态组件,其中有这么一句话:
请留意,这个 attribute 可以用于常规 HTML 元素,但这些元素将被视为组件,这意味着所有的 attribute 都会作为 DOM attribute 被绑定。对于像 value 这样的 property,若想让其如预期般工作,你需要使用 .prop 修饰器。
然后我又去看了下.prop 修饰符的定义:作为一个 DOM property 绑定而不是作为 attribute 绑定。(差别在哪里?)
然后我又去点了这个“差别在哪里”,去到了stackflow,一堆英文我不太想看,于是就搜了下百度,发现下面这篇文章,摘抄如下
明确概念
首先因为两个单词在中文中都翻译成属性,所以会造成较多混淆。在此也先明确一下其它一些基础概念。
身为前端人员我们经常会用标签
,元素
,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"
1234567891011121314151617
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
1234567891011121314151617
value
属性(property)不是完全映射value
属性(attribute)。 初始状态value
属性(property)映射的value
属性(attribute), 当用户手动更改输入框的内容时 , value
属性(property)将更改为用户输入的信息。
<input id="inputId" type="text" value="name">
1
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
1234567891011121314151617
由以上可以得知,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
和事件打交道。