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

时间:2019-05-29 23:32:59

标签: html dom web-component

如何定义一个像<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>却隐式地自动关闭?

2 个答案:

答案 0 :(得分:3)

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

您可以创建从HTMLImageElement扩展的自定义内置元素
以获得自动关闭的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">

答案 1 :(得分:2)

自动关闭标签,称为void elements

AFAIK,无法创建自定义的空元素。总而言之,它需要更改浏览器HTML解析器,这对于Web社区而言并非易事。由于浏览器实现tag-soup algorithm的方式,因此需要进行更改。

因此,您将需要一个结束标记。您可以在此处阅读有关此内容的更多信息:

另一方面,如果您有自己的模板编译器/解析器,例如vue-compilerng-compiler,则可以指示它在构建时了解自动关闭的自定义元素。但是,实现此目标的好处几乎不存在。