如何使用自定义元素将子自定义元素包装到div中

时间:2019-01-25 16:46:42

标签: javascript dom web-component custom-element

我正在尝试创建一个包装器Custom Element,将其子Custom Elements包装到div中。

但是子元素没有包装。而是在子元素之前将空div插入wrapper元素

convert $in -evaluate add -26% -negate -modulate 100,100,0 $out

这是结果:

<script>
  class ListItem extends HTMLElement {
    constructor() {
      super();
    }

    connectedCallback() {
      this.innerHTML = "<div>ListItem</div>";
    }
  }

  class List extends HTMLElement {
    constructor() {
      super();
    }

    connectedCallback() {
      this.innerHTML = `<div class="list">${this.innerHTML}</div>`;
    }
  }

  customElements.define("list-item", ListItem);
  customElements.define("my-list", List);
</script>

<my-list>
  <list-item></list-item>
  <list-item></list-item>
  <list-item></list-item>
</my-list>

我期望以下几点:

<my-list>
  <div class="list"></div>
  <list-item><div>ListItem</div></list-item>
  <list-item><div>ListItem</div></list-item>
  <list-item><div>ListItem</div></list-item>
</my-list>

您可以尝试here

1 个答案:

答案 0 :(得分:3)

这是由于解析执行顺序。检测到<my-list>标签后,即会在插入其子级之前立即创建(并连接)该标签。

因此,${this.innerHTML}将在connectedCallback()中返回一个空字符串。

例如,可以在setTimeout()的帮助下等待子元素的解析:

class List extends HTMLElement {
    connectedCallback() {
        setTimeout( () => 
            this.innerHTML = `<div class="list">${this.innerHTML}</div>` 
        )
    }
}

但是您最好将Shadow DOM与<slot>结合使用,以插入light DOM的元素:

class List extends HTMLElement {
    connectedCallback() {
        this.attachShadow( { mode: 'open' } )
            .innerHTML = `<div class="list"><slot></slot></div>` 
    }
}

请参见下面的示例。

class ListItem extends HTMLElement {
    connectedCallback() {
        this.innerHTML = "<div>ListItem</div>";
    }
}

class List extends HTMLElement {
    connectedCallback() {
        this.attachShadow( { mode: 'open' } )
            .innerHTML = `<div class="list"><slot></slot></div>` 
    }
}

customElements.define("list-item", ListItem);
customElements.define("my-list", List);
<my-list>
    <list-item></list-item>
    <list-item></list-item>
    <list-item></list-item>
</my-list>