如何使用 CSS 选择子类自定义元素

Jar*_*ith 5 javascript css subclassing web-component custom-element

考虑以下:

class MyElem extends HTMLElement {};
customElements.define('my-element', MyElem);

class MyMoreSpecificElem extends MyElem {};
customElements.define('my-more-specific-element', MyMoreSpecificElem);
Run Code Online (Sandbox Code Playgroud)

在对象继承的说法中,第二个类的实例与第一个类具有“is-a”关系: aMyMoreSpecificElem 是 a MyElem

这种关系在 JavaScript 中被捕获:

let subclassInstance = document.querySelector('my-more-specific-element');
let parentClass = document.querySelector('my-element').constructor;

subclassInstance instanceof parentClass; // true
Run Code Online (Sandbox Code Playgroud)

但是我想不出任何MyElem使用 CSS 选择器选择所有s(包括子类 MyMoreSpecificElem)的方法。标签选择器只会获得超类或子类,我知道的所有关系描述选择器(例如~、>)都是关于文档中的位置,而不是类层次结构。

我的意思是,当然,我可以在构造函数中添加一个 CSS 类并通过它进行选择,调用super将确保甚至可以以这种方式选择子类实例。但这很粗糙。有没有办法在纯 CSS 中做到这一点?

Int*_*lia 2

为什么不让基组件类添加className将为基组件类和所有子组件类设置的值或属性。然后你的 CSS 就可以根据这个className值或属性来设置。

class MyBaseEl extends HTMLElement {
  connectedCallback() {
    this.classList.add('my-base-el');
    this.innerHTML = '<div>Base El</div>';
  }
}

customElements.define('my-base-el', MyBaseEl);

class MySubEl extends MyBaseEl {
  connectedCallback() {
    super.connectedCallback();
    this.innerHTML = '<div>Sub El</div>';
  }
}

customElements.define('my-sub-el', MySubEl);
Run Code Online (Sandbox Code Playgroud)
.my-base-el {
  background-color: #FF0;
  display: block;
  outline: 1px dashed black;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.22/webcomponents-lite.js"></script>
<my-base-el></my-base-el>
<my-sub-el></my-sub-el>
Run Code Online (Sandbox Code Playgroud)

这使用一个className值来允许 CSS 获取所有元素或其MyBaseEl子类。

或者像这样:

class MyBaseEl extends HTMLElement {
  connectedCallback() {
    this.setAttribute('my-base-el', '');
    this.innerHTML = '<div>Base El</div>';
  }
}

customElements.define('my-base-el', MyBaseEl);

class MySubEl extends MyBaseEl {
  connectedCallback() {
    super.connectedCallback();
    this.innerHTML = '<div>Sub El</div>';
  }
}

customElements.define('my-sub-el', MySubEl);
Run Code Online (Sandbox Code Playgroud)
[my-base-el] {
  background-color: #FF0;
  display: block;
  outline: 1px dashed black;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.22/webcomponents-lite.js"></script>
<my-base-el></my-base-el>
<my-sub-el></my-sub-el>
Run Code Online (Sandbox Code Playgroud)

这使用一个属性来允许 CSS 获取所有元素或其MyBaseEl子类。

更新

为多个元素标签设置 CSS 的唯一其他方法是了解所有元素标签是什么,并让 CSS 对所有元素标签起作用,如下所示:

my-base-el, my-sub-el, my-other-sub-el, the-third-sub-el {
  background: #000;
  color: #fff;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果其他人可以创建其他子类,那么您需要添加到列表中。

更新2

为什么不直接在基类中设置:host并让它使用 CSS 变量来实现您希望用户能够更改的样式。然后一切都会继承该:hostcss 并按照您想要的方式显示。