繁体   English   中英

为什么更新 DOM 元素的样式属性时 object 传播失败但 Object.assign 成功?

[英]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成功?

例如,在包含的代码片段中, objectAssignDirectobjectAssignIndirect正确设置了background-color ,而objectSpread错误地重置了结果divbackground-color

问题

  1. 为什么会这样? (这是由于克隆问题还是未复制继承属性等属性?)
  2. 有没有办法通过 object 传播来复制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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM