веб-компонент - не принимать дочерние элементы - PullRequest
1 голос
/ 30 мая 2019

Как я могу определить веб-компонент, который работает как <img> в том смысле, что он не принимает дочерние элементы?

  <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 ]

3 голосов
/ 30 мая 2019

Для автономных пользовательских элементов требуется закрывающий тег: Требуется ли для пользовательских элементов закрывающий тег?

Вы можете создать собственный встроенный элемент, расширенный от 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 может иметь только один источник, так что вы можете также создать 3 элемента и использовать

<img is="message-badge">
<img is="message-icon">
<img is="message-image">
2 голосов
/ 30 мая 2019

Самозакрывающиеся теги, известные как void elements .

AFAIK, Невозможно создать пользовательские void элементы .Таким образом, необходимо изменить HTML-парсеры браузера, что непросто для веб-сообщества.Изменения необходимы из-за того, что браузер реализует алгоритм tag-soup .

Таким образом, вам понадобится закрывающий тег. Подробнее об этом можно прочитать здесь:

В примечании, если у вас естьваш собственный шаблонный компилятор / парсер, такой как vue-compiler и ng-compiler, вы, вероятно, можете дать ему команду понимать самозакрывающиеся пользовательские элементы во время сборки.Однако выгоды от этого практически отсутствуют.

...