:host:defined不起作用,:host(:defined)有效

时间:2019-08-29 15:27:07

标签: html css shadow-dom pseudo-class custom-element

在CSS中将:host:defined组合在一起,同时将:host()伪类作品组合在一起时,是不可能的吗?

如下面的示例所示,

:host:defined { display: block; }

无效,而

:host(:defined) { display: block; }

有效。

class CustomElement extends HTMLElement {
  constructor() {
    super();
    this.shadow = this.attachShadow({ mode: 'closed' });
    const css = `
      :host { display: none; }
      :host:defined { display: block; }  
      `;
    this.styles = document.createElement('style');
    this.styles.innerHTML = css;
  }
  connectedCallback() {
    const div = document.createElement('div');
    div.innerHTML = `<code>&lt;${this.tagName.toLowerCase()}&gt;</code> connected!`;
    this.shadow.appendChild(this.styles);
    this.shadow.appendChild(div);
  }
}
class OtherCustomElement extends HTMLElement {
  constructor() {
    super();
    this.shadow = this.attachShadow({ mode: 'closed' });
    const css = `
      :host { display: none; }
      :host(:defined) { display: block; }  
      `;
    this.styles = document.createElement('style');
    this.styles.innerHTML = css;
  }
  connectedCallback() {
    const div = document.createElement('div');
    div.innerHTML = `<code>&lt;${this.tagName.toLowerCase()}&gt;</code> connected!`;
    this.shadow.appendChild(this.styles);
    this.shadow.appendChild(div);
  }
}

customElements.define('custom-element', CustomElement);
customElements.define('other-custom-element', OtherCustomElement);
<custom-element></custom-element>
<other-custom-element></other-custom-element>

上述关于代码笔的代码示例:https://codepen.io/connexo/pen/GRKEGax

1 个答案:

答案 0 :(得分:2)

the specification中,我们可以看到:

  

:host伪类在影子树的上下文中进行评估时,与影子树的影子宿主匹配。在任何其他情况下,它都不匹配

     

函数:host()的伪类具有以下语法::host( <compound-selector-list> )   在阴影树的上下文中进行评估时,如果阴影宿主在其正常上下文中匹配选择器参数,则它与阴影树的阴影宿主匹配。在任何其他情况下,它都不匹配。

基本上,:host将与影子主机匹配,仅此而已。您无法将其与任何其他选择器组合使用。第二种语法允许您在()内添加选择器。

如果您参考规范中显示的示例:

  

假设您有一个带有影子树的组件,如下所示:

<x-foo class="foo">
  <"shadow tree">
    <div class="foo">...</div>
  </>
</x-foo>
  

对于阴影树中的样式表:

     
      
  1. :host<x-foo>元素匹配。

  2.   
  3. x-foo不匹配任何内容。

  4.   
  5. .foo仅匹配元素。

  6.   
  7. .foo:host不匹配

  8.   
  9. :host(.foo)匹配元素。

  10.   

注意(2)和(4)。 (2)什么也没选择,因为没有公共选择器可以在阴影树之外选择。只有:host:host()可以这样做。 (4)没有选择任何内容,因为:host被设计为单独用于选择 shadow主机,但是如果要添加其他选择器,则必须使用:host() (5)。

这里是一个基本的例子来说明:

class CustomElement extends HTMLElement {
  constructor() {
    super();
    this.shadow = this.attachShadow({ mode: 'closed' });
    const css = `
      :host.box { color:red; }  
      `;
    this.styles = document.createElement('style');
    this.styles.innerHTML = css;
  }
  connectedCallback() {
    const div = document.createElement('div');
    div.innerHTML = `<code>&lt;${this.tagName.toLowerCase()}&gt;</code> connected!`;
    this.shadow.appendChild(this.styles);
    this.shadow.appendChild(div);
  }
}
class OtherCustomElement extends HTMLElement {
  constructor() {
    super();
    this.shadow = this.attachShadow({ mode: 'closed' });
    const css = `
      :host(.box) { color:red }  
      `;
    this.styles = document.createElement('style');
    this.styles.innerHTML = css;
  }
  connectedCallback() {
    const div = document.createElement('div');
    div.innerHTML = `<code>&lt;${this.tagName.toLowerCase()}&gt;</code> connected!`;
    this.shadow.appendChild(this.styles);
    this.shadow.appendChild(div);
  }
}

customElements.define('custom-element', CustomElement);
customElements.define('other-custom-element', OtherCustomElement);
<custom-element class="box"></custom-element>
<other-custom-element class="box"></other-custom-element>

现在的问题是:为什么我们可以简单地将:host与任何其他选择器组合在一起,就拥有两种选择器。

这是为了避免在解析选择器时造成混淆和歧义,因为影子主机只能由特殊选择器选择。如果我们编写:host.foo,浏览器将尝试将元素与.foo:host匹配,但这会很棘手,因为.foo只能与阴影树中的元素匹配,而{ {1}}可以走到外面,因此解析选择器以查找是否存在:host以便考虑选择器的其余部分以匹配影子主机是很麻烦的。

使用:host可使浏览器轻松解析选择器,而:host():host没有选择器的特殊情况。

  

注意:这与类似的伪类(例如:host():matches())的特殊性不同,它们仅采用其参数的特殊性。这是因为:not() 肯定是自己选择一个元素,就像“正常”的伪类一样;出于语法原因,它需要一个选择器参数 (我们不能说:host.foo匹配,但.foo不匹配),但在其他方面与只使用:host后跟一个选择器相同。 / p>

请注意,我们不能说:host匹配,但是:host.foo不匹配