HTML attributes 与 DOM properties
属性和特性是完全不同的东西
1 2 3 4 5 6 7 8 9 10 11 12
| <div foo="bar">…</div> <script> const div = document.querySelector('div[foo=bar]');
console.log(div.getAttribute('foo')); console.log(div.foo);
div.foo = 'hello world';
console.log(div.getAttribute('foo')); console.log(div.foo); </script>
|
不同点
HTML 序列化
属性 (Attribute) 序列化为 HTML,而属性 (Property) 则不会:
1 2 3 4 5 6
| const div = document.createElement('div');
div.setAttribute('foo', 'bar'); div.hello = 'world';
console.log(div.outerHTML);
|
值类型
为了以序列化格式工作,Attribute始终是字符串,而Property可以是任何类型:
1 2 3 4 5 6 7 8 9 10
| const div = document.createElement('div'); const obj = { foo: 'bar' };
div.setAttribute('foo', obj); console.log(typeof div.getAttribute('foo')); console.log(div.getAttribute('foo'));
div.hello = obj; console.log(typeof div.hello); console.log(div.hello);
|
区分大小写
Attribute不区分大小写,而Property区分大小写。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div id="test" HeLlO="world"></div> <script> const div = document.querySelector('#test');
console.log(div.getAttributeNames());
div.setAttribute('FOO', 'bar'); console.log(div.getAttributeNames());
div.TeSt = 'value'; console.log(div.TeSt); console.log(div.test); </script>
|
验证、类型强制和默认值
属性 (Property) 带有验证和默认值,而特性 (Attribute) 则没有
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const input = document.createElement('input');
console.log(input.getAttribute('type')); console.log(input.type);
input.type = 'number';
console.log(input.getAttribute('type')); console.log(input.type);
input.type = 'foo';
console.log(input.getAttribute('type')); console.log(input.type);
|
在这种情况下,验证由 getter 处理type。setter 允许无效值’foo’,但当 getter 看到无效值或无值时,它会返回’text’。
某些属性会执行类型强制转换:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <details open>…</details> <script> const details = document.querySelector('details');
console.log(details.getAttribute('open')); console.log(details.open);
details.open = false;
console.log(details.getAttribute('open')); console.log(details.open);
details.open = 'hello';
console.log(details.getAttribute('open')); console.log(details.open); </script>
|
在这种情况下,open属性是一个布尔值,返回属性是否存在。setter 也会强制类型 - 即使给出了 setter ‘hello’,它也会转换为布尔值,而不是直接转换为属性。
属性例如img.height将属性值强制转换为数字。setter 将传入的值转换为数字,并将负值视为 0。
一句话总结
现代前端框架一定程度上降低了对Property和Attribute的关注程度,而采用框架内部的属性管理。在原生HTML情况下,如果可能直接影响到用户(例如,国际化、无障碍、序列化)等相关的尽量用Attribute。前端页面或组件内部的逻辑管理和状态记录尽量用Property。
参考 & 引用
https://jakearchibald.com/2024/attributes-vs-properties/