LitElement 使用按钮附加自定义元素

LitElement appending custom elements using button

我有一个自定义的 LitElement,在它里面,我需要有一个按钮,可以在容器内动态添加新的自定义元素(最好使用 html 函数生成的 TemplateResult 对象):

import { LitElement, html, render } from "lit";
import { customElement } from "lit/decorators.js";

    @customElement('example-custom-component')
    class CustomComponent extends LitElement {

       render() {
          return html`
             <div id="custom-el-container">
             </div>
             <button @click=${this.appendNewCustomEl}>click me!</button>
          `;
       }

       appendNewCustomEl() {
          const templateToAppend = html`
            <another-custom-component>
               some other things added here
            </another-custom-component>
          `;
          render(templateToAppend, this.shadowRoot?.querySelector('#custom-el-container'));
       }
    }

正如您在上面看到的,我试图通过使用渲染函数来实现它,但我没有将它附加到容器的末尾,而是简单地覆盖了 div 的内容。我究竟做错了什么?实现这些结果的最佳方法是什么?请帮忙

编辑: 关于点击事件的评论中我的问题的新示例:

appendNewCustomEl() {
  this.shadowRoot!.querySelector('#custom-el-container').insertAdjacentHTML("beforeend", `
            <another-custom-component>
               <button @click=${this.functionFromCustomComponent}>click me!</button>
            </another-custom-component>
          `)
}

如果你真的想用 lit-html 来做,并且你的容器内容纯粹是你在每次点击按钮时动态呈现的内容,(即不是服务器端呈现的内容)或者你正在使用 lit-html v2 然后你可以有一个列表并跟踪你渲染的内容。类似于:

items=[];

appendNewCustomEl() {
  this.items.push(null);
  const templatesToAppend = this.items.map(() => html`
            <another-custom-component>
               some other things added here
            </another-custom-component>
          `);
   render(templatesToAppend, this.shadowRoot?.querySelector('#custom-el-container'));
}

一般来说,lit-html 擅长并试图实现的是仅更改部分时的最佳 re-render 标记。不需要模板引擎替代车把、小胡子和 co.

在你的例子中,你不需要它,不需要 lit-html:

appendNewCustomEl() {
  this.shadowRoot!.querySelector('#custom-el-container').insertAdjacentHTML("beforeend", `
            <another-custom-component>
               some other things added here
            </another-custom-component>
          `)
}

我稍微修改了您的示例代码,使其更加地道。与其使用 querySelector 和 insertAdjacentHTML,不如以声明方式呈现模板数组。这有一个额外的好处,即您的 functionFromCustomComponent 事件绑定“正常工作”。

我写了完整的例子in a Lit playground

模板列表存储在 reactive propertythis.templates 中,每当更新列表时都会安排高效更新。

然后 this.appendNewCustomEl 方法可以将新模板推送到列表,自动高效渲染会自动发生。

this.templates 使用表达式呈现为 #custom-el-container div:

<div id="custom-el-container">
  ${this.templates}
</div>

有关其他示例,请参阅 Lit expressions documentation

在我的链接示例中,单击时模板列表变为蓝色以演示事件工作。

不是必需的,但相关,Lit.dev 有一个关于 Working with lists 的教程,如果你好奇的话,它会更深入。