让人混淆的前端属性和属性反射大多数人可能分不清 Property 和 Attributes 的细微区别,虽然我们都认为是
前言
大多数人可能分不清 Property 和 Attributes 的细微区别,虽然我们都认为是属性,属性反射也是知之甚少,接下来本文将阐述其中区别及用法。
Attributes
Attributes 是在 HTML 中定义的元素上的键值对:
<div id="myDiv" foo="bar"></div>
我们可以通过 js 的api获取属性值,由于 html 是字符,传递的值默认也会转为字符串的形式:
const myDiv = document.getElementById('myDiv');
console.log(myDiv.attributes);
console.log(myDiv.getAttribute('foo'));
console.log(myDiv.hasAttribute('foo'));
这里需要注意如果传入的是 "false",也会是 true:
// 还是禁用状态 disabled
<button disabled="false"></button>
Properties
相比于 attribute,我们可以防止影响dom的重绘,因为 Properties 是基于 js 对象的,我们可以传入复杂的嵌套结构的引用对象,比如数组或者函数等等。
const myDiv = document.getElementById('myDiv');
myDiv.foo = 'bar';
原则
那么什么时候用 Attributes、Properties呢?
- 使用 JS 时使用 Properties
- 如果只使用 html 就使用 Attributes
- 在使用 Attributes 一定要同步属性变化到 js 的Properties (特殊例子:比如你修改了html的checked,但是从js中获取 dom.checked 是无法同步的最新取值的)
- 不将 Properties 更改同步到相应的 HTML 的Attributes
属性和属性反射
<input type="text" />
console.log(myInput.type); // text
console.log(myInput.getAttribute('type')); // text
如果我们将 type 属性更改为 number ,它将与 property 同步:
myButton.setAttribute('type', 'number');
console.log(myInput.type); // number
但是现在如果我们反着过来,把 js 的 property 修改,那么 html 上的 Attributes 能同步么?
myButton.type = 'date';
console.log(myButton.getAttribute('type')); // date
答案是确实可以,这就是属性反射(Property Reflect),大部分属性都是可以反射到 html 上的。但是也有例外,就是 checked:
<input id="mycheck" type="checkbox" checked />
mycheck.checked = false;
console.log(mycheck.hasAttribute('checked')); // 有问题的 true,应该是false
console.log(mycheck.checked); // false
总结
对于我们平常开发中,我们还是建议从 Attribute 修改更新到 Property,也就是 html 到 js,而不是 js 去更改 html,这是因为自定义的 Property经常更新,每次触发会重绘 DOM 而更影响性能。
转载自:https://juejin.cn/post/7388438687124897846