考虑这个非常基本的计算器(在这里尝试一下):
import {html, css, LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';
@customElement('simple-calc')
export class SimpleCalc extends LitElement {
@property()
value1 = 3
@property()
value2 = 0
render() {
return html`
<input type="number"
.value=${this.value1}
@change=${(e) => this.value1 = e.target.value}>
<input type="number"
.value=${this.value2}
@change=${(e) => this.value2 = e.target.value}>
<p>Difference: ${this.value1 - this.value2}</p>`;
}
}
它按预期工作,只要任一输入的值发生变化,差异就会更新。现在我想做同样的事情,但是
value1
和 value2
不是 LitElement
的“直接”属性,而是属性的属性,即(在这里尝试):
@property()
obj = {value1: 3, value2: 0}
render() {
return html`
<input type="number"
.value=${this.obj.value1}
@change=${(e) => this.obj.value1 = e.target.value}>
<input type="number"
.value=${this.obj.value2}
@change=${(e) => this.obj.value2 = e.target.value}>
<p>Difference: ${this.obj.value1 - this.obj.value2}</p>`;
}
但在这种情况下,差异不会“实时”更新。我怎样才能做到这一点?
Lit 中的反应性基于引用相等性,因此改变对象不会像您所看到的那样触发更新。
有几种方法可以解决这个问题:
this.requestUpdate()
这样做可以让 Lit 知道重新渲染。
@property()
obj = {value1: 3, value2: 0}
render() {
return html`
<input type="number"
.value=${this.obj.value1}
@change=${(e) => {
this.obj.value1 = e.target.value;
this.requestUpdate();
}}>
<input type="number"
.value=${this.obj.value2}
@change=${(e) => {
this.obj.value2 = e.target.value;
this.requestUpdate();
}}>
<p>Difference: ${this.obj.value1 - this.obj.value2}</p>`;
}
这会创建一个新的引用,以便 Lit 可以检测属性更改并重新渲染。
@property()
obj = {value1: 3, value2: 0}
render() {
return html`
<input type="number"
.value=${this.obj.value1}
@change=${(e) => this.obj = {...this.obj, value1: e.target.value}}>
<input type="number"
.value=${this.obj.value2}
@change=${(e) => this.obj = {...this.obj, value2: e.target.value}}>
<p>Difference: ${this.obj.value1 - this.obj.value2}</p>`;
}
像immer这样的库可以帮助处理更复杂的对象。
在这里阅读更多相关信息:https://lit.dev/docs/components/properties/#mutating-properties