Web 组件 - 不接受任何子元素

web component - accept no child elements

如何定义一个像 <img> 一样工作的 Web 组件,因为它不接受任何子元素?

  <script>
    const QA = (q, d) => Array.prototype.slice.call((d||document).querySelectorAll(q), 0);
    const QS = (q, d) => (d||document).querySelector(q);
  </script>

  <template id="push-message">
    <style>
      message { display: grid; font-family: sans-serif; background: #eee; outline: 1px solid; }
      .badge {  }
    </style> 
    <message>
      <img class="badge">
      <img class="icon">
      <img class="image">
    </message>
  </template>

  <script>    
    const wpm = 'push-message';
    customElements.define(wpm,
      class extends HTMLElement {
        constructor() { 
          super();
          const l = QS(`#${wpm}`).content.cloneNode(true);
          const s = this.attachShadow({ mode: 'open' }); s.appendChild(l);
        }
        QS(q) { return QS(q, this.shadowRoot); }
        QA(q) { return QA(q, this.shadowRoot); }  
        static get observedAttributes() { return [ "badge", "icon", "image" ]; }
        attributeChangedCallback(a, o, n) {
          if (/^(badge|icon|image)$/.test(a))
            this.QS(`.${a}`).src = n;
        }
      });
  </script>

  <push-message 
     badge="//google.com/favicon.ico"
      icon="//google.com/favicon.ico"
     image="//google.com/favicon.ico">
  <p>ok</p>

DOM应该是

<push-message></push-message>
<p></p>

没有

<push-message><p></p></push-message>

ok应该显示在结果中。


有没有办法更改 customElements.define 以避免必须显式关闭 <push-message></push-message> 并仅使用 <push-message> 但隐式自关闭?

Self-closing 标签称为 void elements.

据我所知,无法创建自定义空元素。总而言之,它需要更改浏览器 HTML 解析器,这对于网络社区来说并不是一件容易的事。由于浏览器实现 tag-soup algorithm.

的方式,需要进行更改

因此您需要一个结束标记。您可以在此处阅读更多相关信息:

附带说明一下,如果您有自己的模板 compiler/parser,例如 vue-compilerng-compiler,您可以指示它理解 self-closing 自定义元素构建时间。然而,实现这一点的好处实际上是 non-existent.

自治自定义元素需要结束标记:Do custom elements require a close tag?

您可以创建从 HTMLImageElement 扩展的自定义 Built-In 元素
获得一个 self-closing IMG 标签:

<img is="push-message" badge="//google.com/favicon.ico">
<img is="push-message" icon="//google.com/favicon.ico">
<img is="push-message" image="//google.com/favicon.ico">
<p>ok</p>

但是一个IMG只能有一个src,所以你不妨创建3个元素并使用

<img is="message-badge">
<img is="message-icon">
<img is="message-image">