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

Javascript Lit元素,编写受控组件的惯用方法,javascript,web-component,lit-element,controlled-component,Javascript,Web Component,Lit Element,Controlled Component,我正在使用lit元素via,目前正在尝试编写一组嵌套的组件,其中内部组件是一个输入字段,一些祖先组件必须支持一些任意重写规则如“不允许输入数字” 我想弄清楚的是,使用发光元素是构建这个系统的正确方法。在React中,我将使用“受控组件””轻松强制所有组件提交到根组件属性 下面的例子是我使用Lit元素想到的有更好的方法吗 请注意因为我想忽略一些角色,所以挑战变得稍微困难一些。没有e.target.value=this.value在5级,输入元素将在忽略的字符上偏离组件状态。我希望整个组件链能够正确

我正在使用lit元素via,目前正在尝试编写一组嵌套的组件,其中内部组件是一个输入字段,一些祖先组件必须支持一些任意重写规则如“不允许输入数字”

我想弄清楚的是,使用发光元素是构建这个系统的正确方法。在React中,我将使用“受控组件””轻松强制所有组件提交到根组件属性

下面的例子是我使用Lit元素想到的有更好的方法吗

请注意因为我想忽略一些角色,所以挑战变得稍微困难一些。没有
e.target.value=this.value在5级,输入元素将在忽略的字符上偏离组件状态。我希望整个组件链能够正确地同步,因此可以举例说明标题标记

导出类级别1扩展了LitElement{
静态获取属性(){
返回{
值:{type:String}
};
}
render(){
返回html`
${this.value}
`;
}
输入(e){
this.value=e.detail.value.replace(/\d/g');
}
}
...
导出类级别4扩展了LitElement{
静态获取属性(){
返回{
值:{type:String}
};
}
render(){
返回html`
${this.value}
`;
}
}
导出类级别5扩展了LitElement{
静态获取属性(){
返回{
值:{type:String}
};
}
render(){
返回html`
${this.value}
`;
}
输入(e){
let event=new CustomEvent('input-changed'{
详细信息:{value:e.target.value},
泡泡:是的,
镇静:正确
});
e、 target.value=this.value;
本次调度事件(事件);
}
}
导出类AppShell扩展了LitElement{
构造函数(){
超级();
this.value='初始值';
}
render(){
返回html`
`;
}
}

后来添加 另一种方法是在事件中使用path数组直接从根组件访问输入元素

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

onInput(e){
const target=e.path[0];//原始输入元素
this.value=e.path[0].value.replace(/\d/g');
//控制子元素值以符合集合状态
target.value=this.value;
}

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

为了接收更新,让您的组件订阅一个共享的mixin,这是la@mishu的建议,它使用一些状态容器(这里,我提供一些想象的状态解决方案)

从“某些状态解决方案”导入{subscribe};
export const FormMixin=超类=>类扩展超类{
静态获取属性(){return{value:{type:String};}}
connectedCallback(){
super.connectedCallback();
认购(本);
}
}
然后,您可以在
updated
或事件处理程序中处理任何特定于组件的副作用(仅限用户界面-父级或状态容器中的do逻辑)

从“某些状态解决方案”导入{publish};
类Level1扩展了LitElement{
// ...
onInput({detail:{value}}){
发布('value',value.replace(/\d/g',);
} 
}

听起来像是你可以为所有组件使用一个混音器。该mixin将检查父级是否有验证回调,如果有,则在它自己的回调之前调用它(这种方式使其成为一个递归过程)。在这种情况下,这并不容易,我需要影响原始DOM元素和web组件的工作方式,您不能只对祖先中输入字段的更改做出反应,然后期望更改再次传播到DOM中(尽管组件会更新)。然后你需要考虑力的更新,这是另一个问题。如果你可以用上面的例子来证明我错了,我当然会改正我的说法。^ ^ ^您可以使用
事件.composedPath()
方法来获取启动的
。这就是说,这将表单的模型与DOM紧密地联系在一起,而DOM是脆弱的。您可能会考虑使用一些类似于有限状态机或其他类型的状态存储的东西,比如代理服务器,甚至是ReDux商店。输入组件将仅触发与其数据相关的事件,父组件将捕获它们并更新模型或转换状态,更改将通过组件方法向下传播。如果我必须像那样将应用程序与DOM结构耦合,我宁愿在一个地方进行:父组件。