[英]Why does object spread fail but Object.assign succeeds when updating a DOM element's style attribute?
使用 vanilla js 更新 DOM 元素的style
属性时,为什么 object spread 更新失败而Object.assign
成功?
例如,在包含的代码片段中, objectAssignDirect
和objectAssignIndirect
正确设置了background-color
,而objectSpread
错误地重置了结果div
的background-color
。
Object.assign
的所需行为?有几个讨论比较Object.assign
和 object 传播,但似乎没有一个解决这个奇怪的行为:
// Using `Object.assign` directly. const objectAssignDirect = () => { Object.assign(document.querySelector('.myClass').style, { backgroundColor: 'red' }); // Works. console.log('Result should be red'); } // Updating using `Object.assign` with variable. const objectAssignIndirect = () => { const myElement = document.querySelector('.myClass') Object.assign(myElement.style, { backgroundColor: 'blue' }); // Works. console.log('Result should be blue'); } // Using object spread with variable. const objectSpread = () => { const myElement = document.querySelector('.myClass') myElement.style = {...myElement.style, backgroundColor: 'green' }; // Fails. console.log('Result should be green'); }
body { font-size: 2em; }.myClass { width: 100%; height: 50px; background-color: black; color: white; border: 4px solid black; text-align: center; padding: 10px; } button { padding: 15px; margin: 30px; color: white; border-radius: 20px; }.red { background-color: red; }.blue { background-color: blue; }.green { background-color: green; }
<div style="display:flex;justify-content:center;"> <button class="red" onclick="objectAssignDirect();">Use <code>Object.assign</code> directly</button> <button class="blue" onclick="objectAssignIndirect();">Use <code>Object.assign</code> indirectly</button> <button class="green" onclick="objectSpread();">Use object spread</button> </div> <div class="myClass">Result</div>
为什么会这样?
style
是只读属性,不能赋值给新值。
element.style = { ...element.style, backgroundColor: 'green' };
创建element.style
的浅表副本,添加/更新属性backgroundColor
并将副本分配回element.style
。 由于这个原因,它失败了,因为你不能为element.style
分配一个新值。
Object.assign(element.style, { backgroundColor: 'green' });
将第二个参数中的每个属性/值对分配给element.style
。 它不会创建element.style
的副本,但会改变element.style
object。
有没有办法通过 object 传播来复制
Object.assign
的所需行为?
不,object 传播仅用于 object 文字,这将始终导致创建新的 object。 您无法使用 object 扩展更新现有的 object。
直接分配给元素的.style
标记不会导致样式更改。 相反,它会默默地失败:
foo.style = { backgroundColor: 'green' }; console.log(foo.style.backgroundColor);
<div id="foo">foo</div>
您必须分配给现有.style
的属性(现有 CSSStyleDeclaration)才能调用导致 DOM 更改的设置器。 您不能尝试用其他东西完全重新分配style
属性,因为这样您就不会调用 CSSStyleDeclaration 上的特殊设置器。 执行{...myElement.style }
会创建一个新的普通 object,而不是 CSSStyleDeclaration。 Object.assign
在您的两个原始片段中都有效,因为它会调用设置器。
对于此类行为的另一个示例:
const obj = Object.create({ style: { set someProp(arg) { console.log('Setter invoked; changing DOM'); } }}); console.log('Invokes setter:'); obj.style.someProp = 'newVal'; console.log("Doesn't invoke setter:"); obj.style = { someProp: 'newVal' };
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.