Javascript Web 组件 - 添加子项

Javascript Web-Components - add subitems

class Table extends HTMLElement {
  // attributes
  constructor() {
    super();
    this.name = 'undefined';
    this.icon = 'bi-patch-question';
  }

  // component attributes
  static get observedAttributes() {
    return ['name', 'icon', 'properties'];
  }

  // attribute change
  attributeChangedCallback(property, oldValue, newValue) {
    if (oldValue == newValue) return;
    this[ property ] = newValue;
  }

  connectedCallback() {
    const shadow = this.attachShadow({ mode: 'open' });

    shadow.innerHTML = `
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
    <div class="card">
    <table class="table">
      <tr>
          <caption>${this.name}<i class="bi ${this.icon}"></i></caption>
      </tr>
      <!-- here should be the em-tds -->
    </table></div>
    
    <style>
    .card {
      border: 1px solid lightgray;
      border-radius: 15px;
      margin: 10px 0;
      padding: 15px;
    }
  
    table {
        width: 100%;
        border-collapse: collapse;
    }

    tr {
      border-top: 1px solid lightgrey;
    }

    tr:first-child {
      border: none;
    }

    td {
      width: 100%;
      padding: 7px;
      font-size: 18px;
      vertical-align: middle;
    }

    caption {
        position: relative;
        font-family: ExtraBold;
        padding: 7px;
        margin-bottom: 5px;
        text-align: left;
        font-size: 18px;
        text-decoration: 2px underline;
    }

    caption i {
      position: absolute;
      right: 6px;
      font-size: 22px;
    }
    </style>
    `
  }
}

class TableTds extends HTMLElement {
  // attributes
  constructor() {
    super();
    this.name = 'undefined';
    this.value = 'undefined';
  }

  // component attributes
  static get observedAttributes() {
    return ['name', 'value'];
  }

  // attribute change
  attributeChangedCallback(property, oldValue, newValue) {
    if (oldValue == newValue) return;
    this[ property ] = newValue;
  }

  connectedCallback() {
    const shadow = this.attachShadow({ mode: 'open' });

    shadow.innerHTML = `
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
    <td>${this.name}</td>
    <td>${this.value}></td>
    `
  }
}




customElements.define('em-table', Table);
customElements.define('em-td', TableTds);
<em-table name="test">
  <em-td name="test" value="10"></em-td>
  <em-td name="test" value="10"></em-td>
</em-table>

我正在为我的平台开发新的网络组件,运行 遇到了一些问题。创建网络组件对我来说很好,但我想在网络组件的标签内创建子组件。显然这没有用,因为该组件受到保护,不受其他一切影响...

在我的例子中,它是关于一个 table 网络组件,我想在其中将 html-tds 作为子组件,以便稍后正确使用它们。

我试过使用插槽,但没用...

这应该可以帮助您入门,您需要自己添加更多内容。

要点是不是将所有内容包装在 shadowDOM 中,
让你的 em-td 找到他们的“table”,而不必通过 shadowroot 边界
刺穿 UP 有:

    connectedCallback() {
      this.closest("em-table")
          .shadowRoot
          .querySelector("table")
          .append(this.tr);
    }
工作片段:

注意:在这里使用 声明式 shadowDOM <template shadowroot="open"> for em-table
如果您不想从 SSR/HTML

开始,可以将其全部移动到 constructor

<em-table name="test">
  <template shadowroot="open">
    <div class="card">
      <table class="table">
        <caption></caption>
      </table>
    </div>
    <style>
      tr{background:pink}
    </style>
  </template>
  <em-td name="test1" value="10"></em-td>
  <em-td name="test2" value="20"></em-td>
</em-table>
<script>
  customElements.define('em-table', class extends HTMLElement {
    caption(name, icon) {
      let html = `${name}<i class="bi ${icon}"></i>`;
      this.shadowRoot.querySelector("caption").innerHTML = html;
    }
    connectedCallback() {
      this.caption('caption', 'bi-patch-question');
    }
    static get observedAttributes() {
      return ['name', 'icon', 'properties'];
    }
    attributeChangedCallback(property, oldValue, newValue) {
      if (oldValue == newValue) return;
      this[property] = newValue;
    }
  });
  customElements.define('em-td', class extends HTMLElement {
    static get observedAttributes() {
      return ['name', 'value'];
    }
    constructor() {
      super();
      this.tr = document.createElement("tr");
      this._name = document.createElement("td");
      this._value = document.createElement("td");
      this.tr.append(this._name, this._value);
    }
    attributeChangedCallback(property, oldValue, newValue) {
      if (oldValue == newValue) return;
      this[property] = newValue;
    }
    set name(v) {
      this._name.innerText = v;
    }
    set value(v) {
      this._value.innerText = v;
    }
    connectedCallback() {
      this.closest("em-table")
          .shadowRoot.querySelector("table")
          .append(this.tr);
    }
  });
</script>

注意:

来自 MDN 上的 <TR> 文档:

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr

Permitted parents

<table> (only if the table has no child <tbody> element, and even then only after any <caption>, <colgroup>, and <thead> elements); otherwise, the parent must be <thead>, <tbody> or <tfoot>

所以

<em-table>
  <tr>

有效HTML