首页 > 解决方案 > 使用 CSS 引用 Web 组件根属性

问题描述

创建了一个带有影子 DOM 的 Web 组件。单击按钮时,它会将open属性添加到 Web 组件。

open当添加 CSS 样式时,我想在 CSS 中显示隐藏的 div 。阴影 DOM 样式是否可以引用 Web 组件根目录上的属性?否则,我必须在影子 DOM 中添加一个多余的类或属性。

class CustomComponent extends HTMLElement {
  constructor() {
    super();
    
    this.element = this.attachShadow({mode: 'open'});
  }
  
  static get observedAttributes() {
    return ['open'];  
  }
  
  attributeChangedCallback(attrName, oldValue, newValue) {
    if (newValue !== oldValue) {
      this[attrName] = this.hasAttribute(attrName);
    }
  }
  
  connectedCallback() {
    const template = document.getElementById('custom-component');
    const node = document.importNode(template.content, true);
    this.element.appendChild(node);
    
    this.element.querySelector('button').addEventListener('click', () => {
      this.setAttribute('open', '');
    });
  }
}

customElements.define('custom-component', CustomComponent);
<template id="custom-component">
  <style>
    div {
      display: none;
    }
    [open] div {
      display: block;
    }
  </style>
  <button>Open</button>
  <div>Content</div>
</template>

<custom-component></custom-component>

标签: javascriptcssweb-componentshadow-dom

解决方案


看来hostCSS 伪选择器旨在处理这种精确情况。

class CustomComponent extends HTMLElement {
  constructor() {
    super();
    
    this.element = this.attachShadow({mode: 'open'});
  }
  
  static get observedAttributes() {
    return ['open'];  
  }
  
  attributeChangedCallback(attrName, oldValue, newValue) {
    if (newValue !== oldValue) {
      this[attrName] = this.hasAttribute(attrName);
    }
  }
  
  connectedCallback() {
    const template = document.getElementById('custom-component');
    const node = document.importNode(template.content, true);
    this.element.appendChild(node);
    
    this.element.querySelector('button').addEventListener('click', () => {
      this.setAttribute('open', '');
    });
  }
}

customElements.define('custom-component', CustomComponent);
<template id="custom-component">
  <style>
    div {
      display: none;
    }
    :host([open]) div {
      display: block;
    }
  </style>
  <button>Open</button>
  <div>Content</div>
</template>

<custom-component></custom-component>


推荐阅读