【问题标题】:getComputedStyle() returns nothing, but getComputedStyle().getPropertyValue() returns as expectedgetComputedStyle() 不返回任何内容,但 getComputedStyle().getPropertyValue() 按预期返回
【发布时间】:2021-08-16 13:54:29
【问题描述】:

我正在尝试将一个元素从 light DOM 移动到 shadow 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

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

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

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

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

任何帮助将不胜感激,在此先感谢。

编辑:我采用了下面 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>

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

【问题讨论】:

  • 全局 CSS 不设置 shadowDOM 的样式,这是 shadowDOM 的主要用途。如果您在 DOM 中有单独的样式标签,您可以将其移动或复制到 shadowDOM
  • @Danny'365CSI'Engelman “您可以将其移动或复制到 shadowDOM”,是的,我正在尝试这样做,但以编程方式而不是手动方式。这就是我遇到的问题,即轻型 DOM 元素的 getComputedStyle() 由于某种原因为空白

标签: javascript css web web-component


【解决方案1】:

来自 MDN 文档:

Window.getComputedStyle() 方法在应用活动样式表并解析这些值可能包含的任何基本计算之后,返回一个包含元素所有 CSS 属性值的对象。 可以通过对象提供的 API 或使用 CSS 属性名称进行索引来访问各个 CSS 属性值。

上面说需要使用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;
}
&lt;div class="card"&gt;&lt;/div&gt;

【讨论】:

  • 是的,它声明“单个 CSS 属性值是通过对象提供的 API 或通过使用 CSS 属性名称进行索引来访问的。”,但我希望复制整张纸。来自docs you linked:“返回的对象与从元素的样式属性返回的对象具有相同的 CSSStyleDeclaration 类型。”所以我应该能够做到shadow_elem.style = window.getComputedStyle(light_elem) 对吗?但是由于某种原因,light DOM 元素的getComputedStyle() 是空的。
  • @ADSmith-0 您需要逐个访问所有属性,因为您不能一次打印整个getComputedStyle()
  • 如果是STYLE元素,又不想用appendChild移动,也可以抓取它的innerHTML
【解决方案2】:
  1. 属性style只读,因此您不能为其分配任何内容;
    (我根据 cmets 进行纠正;您可以指定一个值,但它 将覆盖所有值)

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

  3. 如果您将 lightDOM 内容反射到 shadowDOM 中的 &lt;slot&gt;,则无需复制样式,因为来自 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>

更多阅读:

【讨论】:

  • "属性样式是只读的,所以你不能给它分配任何东西" 这不是真的,它是一个PutForwards=cssText drafts.csswg.org/cssom/#elementcssinlinestyle 这意味着设置这个属性将设置.cssText 的实际的CSSStyleDeclaration,这正是 OP 尝试使用它的方式。
猜你喜欢
  • 1970-01-01
  • 2014-04-01
  • 2012-07-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 2011-05-12
  • 1970-01-01
相关资源
最近更新 更多