使用 lit-html 呈现的嵌套 HTML 元素会覆盖父模板

Nested HTMLElement rendered with lit-html overwrites parent's template

我有两个最小的 HTML 元素:一个 AppRoot 和一个 SubElement。元素的内部 HTML 是通过 lit-html 的 renderhtml 模板函数生成的。

AppRoot的HTML模板是一个div,里面有两段:一段显示message属性的文本,另一段实例化一个SubElement 并传递给它一个字符串。

SubElement 的 HTML 模板只是传递的字符串。

我希望呈现的 HTML 看起来像这样:

<div>
    <p>AppRoot's message</p>
    <p>The string passed to SubElement</p>
</div>

但实际上只是SubElement的渲染模板:

The string passed to SubElement

为什么 SubElement 的模板在渲染时会替换 AppRoot 的模板?我尝试过更改标签(用 div、段落括起来),但无济于事。

您可以在下面找到源代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src="./index.js" type="module"></script>
    <app-root></app-root>
</body>
</html>
import { render, html } from './node_modules/lit-html/lit-html.js';


class SubElement extends HTMLElement {

    constructor(message) {
        super();
        this.message = message;
    }

    connectedCallback() {
        this.innerHTML = render(this.template(), document.body);;
    }

    template() {
        return html`
            ${this.message}
        `;
    }

}

customElements.define('sub-element', SubElement);


class AppRoot extends HTMLElement {

    constructor() {
        super();
        this.message = "I am root!";
    }

    connectedCallback() {
        this.innerHTML = render(this.template(), document.body);
    }

    template() {
        return html`
            <div>
                <p>${this.message}</p>
                <p>${new SubElement("I am not root!")}</p>
            </div>
        `;
    }

}

customElements.define('app-root', AppRoot);

render 的第二个参数是模板应该呈现的容器。每个组件当前正在将模板结果渲染到文档主体并覆盖以前渲染的结果。

connectedCallback() {
    this.innerHTML = render(this.template(), document.body);
}

您应该考虑使用 shadow DOM 或在组件本身内渲染。

connectedCallback() {
    render(this.template(), this);
}