getComputedStyle() returns 没什么,但 getComputedStyle().getPropertyValue() returns 符合预期

getComputedStyle() returns nothing, but getComputedStyle().getPropertyValue() returns as expected

我试图将一个元素从灯光 DOM 移动到阴影 DOM,但是当我这样做时样式没有复制过来。我试图通过设置 newElement.style = window.getComputedStyle(elem) 来解决这个问题,但这似乎不起作用。样式应为:

.card {
    color: #ff0;
    font-size: 3rem;
    font-weight: 600;
    border: 3px solid blueviolet;
    background-color: greenyellow;
}

但是样式不适用,当我打印 getComputedStyle() 来安慰我时,我看到的是: all the values are empty

但是,当我像这样使用 .getPropertyValue() 遍历 getComputedStyle() 的属性时:

for(let property of style){
    console.log(`property: ${property}, value: ${style.getPropertyValue(property)}`);
}

我在控制台中得到的是: the correct values

所以我很困惑为什么 getComputedStyle() 不包含值,但使用 getComputedStyle().getPropertyValue() returns 正确的值。我确定我遗漏了一些明显的东西,因为我在任何地方都找不到关于此的另一个 post。

任何帮助将不胜感激,提前致谢。

编辑: 我已经采用了下面 Danny 提供的代码并对其进行了修改以更好地显示我面临的问题:

<style>
  .card {
    color: yellow;
    background: green;
  }
</style>

<my-element>
  <div class="card">lightDOM reflected to shadowDOM</div>
</my-element>

<script>
  customElements.define("my-element", class extends HTMLElement {
    constructor(){
        super().attachShadow({mode:"open"}).innerHTML = ``;
    }
    connectedCallback() {
      setTimeout(() => { // wait till innerHTML is parsed
        let card = this.children[0]; // Get the light DOM Card element
        this.shadowRoot.appendChild(card.cloneNode(true)); // Append it to the shadowDOM
        let style = window.getComputedStyle(card); // Get style of the Light DOM Card
        this.shadowRoot.querySelector('.card').style = style; // Set the ShadowDOM card style equal to the Light DOM Style
        console.log(style);
        console.log(style.color);      // yellow = rgb:255,255,0
        console.log(style.background); // green  = rgb:0,128,0
        card.remove(); // Remove the card from the Light DOM to prevent duplication
      })
    }
  })
</script>

请注意,上面的样式并不适用,即使它看起来与文档指定的完全一样: "返回的对象与从元素样式返回的对象具有相同的 CSSStyleDeclaration 类型 属性。但是,这两个对象的用途不同:

来自 MDN 文档:

The Window.getComputedStyle() method returns an object containing the values of all CSS properties of an element, after applying active stylesheets and resolving any basic computation those values may contain. Individual CSS property values are accessed through APIs provided by the object, or by indexing with CSS property names.

说明需要使用API函数,比如getPropertyValue()来获取它的值

参考:https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

如果您想打印特定元素的所有 CSS 样式,您可以像这样迭代所有属性:

function dumpCSSText(element){
  var s = '';
  var o = getComputedStyle(element);
  for(var i = 0; i < o.length; i++){
    s+=o[i] + ': ' + o.getPropertyValue(o[i])+';\n';
  }
  return s;
}

var e = document.querySelector('.card');
console.log(dumpCSSText(e));
.card {
    color: #ff0;
    font-size: 3rem;
    font-weight: 600;
    border: 3px solid blueviolet;
    background-color: greenyellow;
}
<div class="card"></div>

  1. 属性 style只读的 所以你不能给它赋值;
    (我根据评论进行更正;您可以指定一个值,但它 将覆盖所有值)

  2. 自定义元素的 innerHTMLconnectedCallback 触发时 尚未解析 。因此,使用 getComputedStyle 获取其子元素的样式是对不存在元素的操作。

  3. 如果您反射 lightDOM 内容到 shadowDOM 中的 <slot>,则无需复制样式,因为 lightDOM 的样式是 反射

<style>
  .card {
    color: yellow;
    background: green;
  }
</style>

<my-element>
  <div class="card">lightDOM reflected to shadowDOM</div>
</my-element>

<script>
  customElements.define("my-element", class extends HTMLElement {
    constructor(){
        super().attachShadow({mode:"open"}).innerHTML = `<slot></slot>`
    }
    connectedCallback() {
      setTimeout(() => { // wait till innerHTML is parsed
        let card = this.querySelector(".card"); // in lightDOM!
        let style = window.getComputedStyle(card);
        console.log(style.color);      // yellow = rgb:255,255,0
        console.log(style.background); // green  = rgb:0,128,0
      })
    }
  })
</script>

更多阅读: