5

我正在通过@open-wc使用lit-elements,目前正在尝试编写一组嵌套的组件,其中内部组件是输入字段,并且某些祖先组件必须支持一些任意重写规则,例如“不允许输入数字” '。

我想弄清楚的是使用 lit-elements 构建它的正确方法是什么。在React中,我将使用“受控组件”,请参见此处轻松强制所有组件提交到根组件属性。

下面的示例是我使用 Lit-Elements 提出的。有更好的方法吗?

请注意; 因为我想忽略一些角色,所以挑战变得稍微困难​​了。如果没有e.target.value = this.value;at level-5,输入元素将与忽略字符上的组件状态不同。我希望整个组件链正确同步,因此要举例说明标题标签。

export class Level1 extends LitElement {
  static get properties() {
    return {
      value: { type: String }
    };
  }

  render() {
    return html`
      <div>
        <h1>${this.value}</h1>
        <level-2 value=${this.value} @input-changed=${this.onInput}></level-2>
      </div>`;
  }

  onInput(e) {
    this.value = e.detail.value.replace(/\d/g, ''); 
  }
}

...

export class Level4 extends LitElement {
  static get properties() {
    return {
      value: { type: String }
    };
  }

  render() {
    return html`
      <div>
        <h4>${this.value}</h4>
        <level-5 value=${this.value}></level-5>
      </div>`;
  }
}

export class Level5 extends LitElement {
  static get properties() {
    return {
      value: { type: String }
    };
  }

  render() {
    return html`
      <div>
        <h5>${this.value}</h5>
        <input .value=${this.value} @input=${this.onInput}></input>
      </div>`;
  }

  onInput(e) {
    let event = new CustomEvent('input-changed', {
      detail: { value: e.target.value },
      bubbles: true,
      composed: true
    });

    e.target.value = this.value;
    this.dispatchEvent(event);
  }
}

export class AppShell extends LitElement {
  constructor() {
    super();
    this.value = 'initial value';
  }

  render() {
    return html`
      <level-1 value=${this.value}></level-1>
    `;
  }
}

稍后添加

一种方法是在事件中使用路径数组直接从根组件访问输入元素。

我认为这是一个更糟糕的解决方案,因为它导致组件之间的耦合更强,即假设子组件是具有 value 属性的输入元素。

  onInput(e) {
    const target = e.path[0]; // origin input element
    this.value = e.path[0].value.replace(/\d/g, ''); 
    // controlling the child elements value to adhere to the colletive state
    target.value = this.value;
  }
4

1 回答 1

0

不要编写你的事件,用你的逻辑在大父级中处理它们。让孩子在事件中发送所有需要的信息,尽量不要依赖于target父母的事件处理程序。

要接收更新,请让您的组件订阅一个共享的 mixin,这是 @mishu 的建议,它使用一些状态容器(在这里,我提出了一些虚构的状态解决方案)

import { subscribe } from 'some-state-solution';
export const FormMixin = superclass => class extends superclass {
  static get properties() { return { value: { type: String }; } } 
  connectedCallback() {
    super.connectedCallback();
    subscribe(this);
  }
}

然后您可以在事件处理程序或事件处理程序中处理任何特定于组件的副作用updated(仅限 UI - 在父容器或状态容器中执行逻辑)

import { publish } from 'some-state-solution';
class Level1 extends LitElement {
  // ...
  onInput({ detail: { value } }) {
    publish('value', value.replace(/\d/g, '')); 
  } 
}
于 2019-12-10T14:46:18.483 回答