在另一个内部创建一个 web 组件并将其附加到另一个上是否是一种不好的做法?

Is it bad practice to create a web-component inside another and append it to said other?

基本上我有一个 Web 组件 "x" 并且我在 "x" 中动态创建了一个表单组件,它将附加到 "x".

当然,我可以在创建 "x" 的地方进行,在创建 "x" 之后。

基本上是这样的:

class X extends LitElement {

  render() {
    return html`
      <div>
        <slot name="form-component">${this.appendFormComponent()}</slot>
      </div>
      <slot></slot>
    `
  }

  appendFormComponent() {
    const formComponent = document.createElement('input')
    formComponent.slot = "form-component"
    this.append(formComponent)
  }

  // side note, is running this append inside the render function a terrible 
  // idea and where should I do it instead? I mean doing it in the render 
  // function does appear to work...
}

正如您所怀疑的,这绝对是一个糟糕的想法,因为您将 命令式 范式与 声明式 范式混合在一起。但是,如果您确实需要这样做并且因为您正在使用 LitElement,您可以使用适当的生命周期方法很好地抽象声明性和命令性 UI 代码:

class X extends LitElement {

  render() {
    return html`
      <div>
        <slot name='form-component'></slot>
      </div>
      <slot></slot>
    `;
  }

  // Executed only once
  firstUpdated() {
    const formComponent = document.createElement('input');

    formComponent.slot = 'form-component';    
    this.append(formComponent);
  }
}

此外,您尝试的方法可能存在问题。仅通过渲染功能即可轻松解决您的问题:

class X extends LitElement {

  render() {
    return html`
      <div>
        <slot name='form-component'>
          <!-- Notice the use of INPUT TAG here -->
          <input type='text' />
        </slot>
      </div>
      <slot></slot>
    `;
  }
}

使用 firstUpdateddocument.createElement 之类的东西应该用来创建 UI 组件,这些组件具有打破 UI 作为函数的偏移元素State 概念。这些组件是日期选择器、多 select 下拉菜单、对话框等,它们直接将 DOM 元素附加到 body 以准确管理 Z-index 和固定定位。

此外,根据您的评论,如果您有需要分配给输入文本的动态函数,只需创建一个包装函数,例如:

class X extends LitElement {

  // Input change event handler
  onChange() {

    // A guard to check presence of dynamic function
    if (this.someDynamicFuction) {
      this.someDynamicFuction();
    }
  }

  render() {
    return html`
      <div>
        <slot name='form-component'>
          <!-- Notice the use of INPUT TAG here -->
          <input type='text' @change=${this.onChange} />
        </slot>
      </div>
      <slot></slot>
    `;
  }
}