【问题标题】:Self-closing custom element not displaying when immediately preceded by another self-closing custom element当紧跟在另一个自关闭自定义元素之前时,自关闭自定义元素不显示
【发布时间】:2020-10-19 18:33:14
【问题描述】:

我正在使用标准自定义元素和自闭合自定义元素。

当声明彼此紧邻时,它们并没有像我预期的那样完全工作。

如果我编写两个彼此紧邻的标准自定义元素:

<colour-list scheme="rainbow"></colour-list>
<colour-list scheme="zebra"></colour-list>

它们都正常显示:

const schemes = {
  rainbowJSON : '["red", "orange", "yellow", "green", "blue", "indigo", "violet"]',
  zebraJSON : '["black", "white", "black", "white", "black"]'
}

class colourList_CustomElement extends HTMLElement {
  
  constructor() {
    super();
    this.root = this.attachShadow({mode: "open"});
  }

  connectedCallback() {

    this.root.innerHTML = `
    
      <style>
        :host {
          display: inline-block;  /* <= Because Custom elements are display:inline by default */
          contain: content;  /* <= Because this delivers an immediate performance win */
        }
        
        ul {
          margin: 0 24px 0 0;
          padding: 0;
          width: 200px;
          list-style-type: none;
        }
        
        li {
          height: 24px;
          text-align: center;
          font-weight: bold;
          text-shadow: 1px 1px rgba(0, 0, 0, 0.7);
        }
        
      </style>
      
    `;
    
    let schemeJSON = schemes[this.getAttribute('scheme') + 'JSON'];
    let colours = JSON.parse(schemeJSON);
    let colourList = document.createElement('ul');
    let listItem;
    
    for (let colour of colours) {
    
      listItem = document.createElement('li');
      let textShadow = (colour === 'black') ? 'text-shadow: 1px 1px rgba(255, 255, 255, 0.7);' : '';
      listItem.setAttribute('style', 'color: '+ colour + '; background-color: ' + colour + ';' + textShadow);
      listItem.textContent = colour;
      colourList.appendChild(listItem);

    }
    
    this.root.appendChild(colourList);
  }
}

customElements.define('colour-list', colourList_CustomElement);
<colour-list scheme="rainbow"></colour-list>
<colour-list scheme="zebra"></colour-list>

或者,如果我有一个紧跟标准自定义元素的自闭合自定义元素:

<colour-list scheme="rainbow"></colour-list>
<colour-list scheme="zebra" />

它们也都正常显示:

const schemes = {
  rainbowJSON : '["red", "orange", "yellow", "green", "blue", "indigo", "violet"]',
  zebraJSON : '["black", "white", "black", "white", "black"]'
}

class colourList_CustomElement extends HTMLElement {
  
  constructor() {
    super();
    this.root = this.attachShadow({mode: "open"});
  }

  connectedCallback() {

    this.root.innerHTML = `
    
      <style>
        :host {
          display: inline-block;  /* <= Because Custom elements are display:inline by default */
          contain: content;  /* <= Because this delivers an immediate performance win */
        }
        
        ul {
          margin: 0 24px 0 0;
          padding: 0;
          width: 200px;
          list-style-type: none;
        }
        
        li {
          height: 24px;
          text-align: center;
          font-weight: bold;
          text-shadow: 1px 1px rgba(0, 0, 0, 0.7);
        }
        
      </style>
      
    `;
    
    let schemeJSON = schemes[this.getAttribute('scheme') + 'JSON'];
    let colours = JSON.parse(schemeJSON);
    let colourList = document.createElement('ul');
    let listItem;
    
    for (let colour of colours) {
    
      listItem = document.createElement('li');
      let textShadow = (colour === 'black') ? 'text-shadow: 1px 1px rgba(255, 255, 255, 0.7);' : '';
      listItem.setAttribute('style', 'color: '+ colour + '; background-color: ' + colour + ';' + textShadow);
      listItem.textContent = colour;
      colourList.appendChild(listItem);

    }
    
    this.root.appendChild(colourList);
  }
}

customElements.define('colour-list', colourList_CustomElement);
<colour-list scheme="rainbow"></colour-list>
<colour-list scheme="zebra" />

但是,最后,如果我有两个自闭合元素,一个紧跟在前一个之后,第二个自定义元素根本不会显示:

<colour-list scheme="rainbow" />
<colour-list scheme="zebra" />

const schemes = {
  rainbowJSON : '["red", "orange", "yellow", "green", "blue", "indigo", "violet"]',
  zebraJSON : '["black", "white", "black", "white", "black"]'
}

class colourList_CustomElement extends HTMLElement {
  
  constructor() {
    super();
    this.root = this.attachShadow({mode: "open"});
  }

  connectedCallback() {

    this.root.innerHTML = `
    
      <style>
        :host {
          display: inline-block;  /* <= Because Custom elements are display:inline by default */
          contain: content;  /* <= Because this delivers an immediate performance win */
        }
        
        ul {
          margin: 0 24px 0 0;
          padding: 0;
          width: 200px;
          list-style-type: none;
        }
        
        li {
          height: 24px;
          text-align: center;
          font-weight: bold;
          text-shadow: 1px 1px rgba(0, 0, 0, 0.7);
        }
        
      </style>
      
    `;
    
    let schemeJSON = schemes[this.getAttribute('scheme') + 'JSON'];
    let colours = JSON.parse(schemeJSON);
    let colourList = document.createElement('ul');
    let listItem;
    
    for (let colour of colours) {
    
      listItem = document.createElement('li');
      let textShadow = (colour === 'black') ? 'text-shadow: 1px 1px rgba(255, 255, 255, 0.7);' : '';
      listItem.setAttribute('style', 'color: '+ colour + '; background-color: ' + colour + ';' + textShadow);
      listItem.textContent = colour;
      colourList.appendChild(listItem);

    }
    
    this.root.appendChild(colourList);
  }
}

customElements.define('colour-list', colourList_CustomElement);
<colour-list scheme="rainbow" />
<colour-list scheme="zebra" />

我不清楚为什么在最后一个示例中两个元素都没有显示。

【问题讨论】:

  • 自治自定义元素不能自动关闭。只有定制的内置元素(如 IMG)可以......但 Apple 拒绝实现定制的内置元素。
  • 给你:github.com/w3c/webcomponents/issues/624 rniwa 是 Apple,annevk 是 Mozilla,hayatoito 是 Google
  • 没有自定义的自动关闭元素。自闭合(无效)元素是precisely defined exceptions to the normal parsing algorithm,用于imgbrmetainput 和其他一些元素。始终明确关闭您的元素。你得到的是两个缺少结束标签的嵌套元素。
  • 这是一个很棒的链接@Danny'365CSI'Engelman - 非常感谢。我分享了该线程中许多参与者对自动关闭自定义元素的热情。我也明白为什么 void 自定义元素很难解析,但肯定不是自关闭自定义元素(?)自关闭自定义元素的正则表达式是:^\&lt;[a-z][\-]*\-[\-]*\s?\/\&gt;$

标签: javascript html custom-element


【解决方案1】:

从上面的 cmets 继续...

请注意,您可以创建 Unknown 元素(创建 FOUC),您可以 querySelect,处理成您想要的内容,然后从 DOM 中删除

<my-elements>
  <green id=foo />
  <red id=bar />
  Bye Bye World
</my-elements>

Hello World!


<script>
  customElements.define('my-elements', class extends HTMLElement {
    connectedCallback() {
      setTimeout(() => {
        this.append(...[...this.querySelectorAll("*")].map(node => {
          console.log(node.outerHTML);
          let div = document.createElement("div");
          div.style.color = node.nodeName;
          div.innerHTML = `${node.id} ${node.nodeName}`;
          node.remove();
          return div;
        }));
      });
    }
  });
</script>

【讨论】:

  • 感谢@Danny'365CSI'Engelman。如果您乐于将非常有用的 cmets / 链接从上面复制并粘贴到您的问题中,那将使它变得更好。谢谢。
猜你喜欢
  • 2019-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-23
  • 2022-01-16
  • 2019-05-08
  • 2018-09-18
  • 1970-01-01
相关资源
最近更新 更多