html - :host:defined doesn't work,:主机(:定义)有效

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

<分区>

是否不可能或不允许合并 :host:defined在 CSS 中,同时将后者与 :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>

codepen 上面的代码示例:https://codepen.io/connexo/pen/GRKEGax

最佳答案

来自 the specification我们可以阅读:

The :host pseudo-class, when evaluated in the context of a shadow tree, matches the shadow tree’s shadow host. In any other context, it matches nothing

The :host() function pseudo-class has the syntax: :host( <compound-selector-list> ) When evaluated in the context of a shadow tree, it matches the shadow tree’s shadow host if the shadow host, in its normal context, matches the selector argument. In any other context, it matches nothing.

基本上,:host将匹配影子主机,仅此而已。您不能将它与任何其他选择器组合 虽然第二种语法允许您在 () 中添加一个选择器.

如果您引用规范中显示的示例:

say you had a component with a shadow tree like the following:

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

For a stylesheet within the shadow tree:

  1. :host matches the <x-foo> element.

  2. x-foo matches nothing.

  3. .foo matches only the element.

  4. .foo:host matches nothing

  5. :host(.foo) matches the element.

注意 (2) 和 (4)。 (2) 没有选择任何东西,因为没有公共(public)选择器可以选择影子树之外的东西。只有:host:host()可以做。 (4) 没有选择任何内容,因为 :host旨在单独用于选择 shadow host 但如果您想添加另一个选择器,则必须使用 :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 :host 只能匹配影子树内的一个元素可以出去所以解析选择器以查找是或否我们有 :host在里面为了考虑选择器的剩余部分来匹配影子主机将是乏味的。

使用 :host()让浏览器更容易解析选择器和:host:host() 的特例没有选择器。

Note: This is different from the specificity of similar pseudo-classes, like :matches() or :not(), which only take the specificity of their argument. This is because :host is affirmatively selecting an element all by itself, like a "normal" pseudo-class; it takes a selector argument for syntactic reasons (we can’t say that :host.foo matches but .foo doesn’t), but is otherwise identical to just using :host followed by a selector.

请注意 我们不能说 :host.foo匹配但.foo没有

关于html - :host:defined doesn't work,:主机(:定义)有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59336696/

上一篇:css - 当 style.css 中的 bookdown 字体发生变化时,Serif 不起作用

下一篇:html - 如何使图像网格响应?

相关文章:

css - ul 内每个 li 的宽度不同

javascript - 查找元素的可滚动容器,包括在影子 DOM 中

css - 覆盖 app-header-layout 的影子 DOM 样式

html - 在 CSS div 表中格式化图像

html - css类的动态宽度::伪元素之后

javascript - 错误不会显示在以 html 形式提交的表单上的 span 标记中 - Jquery

javascript - 使用 webview 但不使用 Shadowprotect 创建 NW.js

html - 当 Bootstrap Modal 打开时,滚动条会改变方向

html - 单击 URL 'bumps' 文本/图像一点

c# - 需要在 asp 下拉列表中选择颜色