Lit元素,编写受控组件的惯用方法



我正在通过@open wc处理lit元素,并且目前正在尝试编写一组嵌套组件,其中内部组件是输入字段并且某些祖先组件必须支持一些任意重写规则(如"不允许输入数字"(。

我想弄清楚的是使用照明元素构建它的正确方法是什么。在React中,我会使用">受控组件",请参阅此处,轻松地强制所有组件提交到根组件属性。

下面的例子是我使用Lit Elements得出的有更好的方法吗

请注意因为我想忽略一些角色,所以挑战变得稍微困难一些。如果没有第5级的e.target.value = this.value;,输入elment将偏离被忽略字符的组件状态。我希望整个组件链正确同步,因此可以举例说明头标签。

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;
}

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

为了接收更新,让你的组件订阅一个共享的mixin,这是la@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, '')); 
} 
}

最新更新