onChange 未在 litElement 的输入字段中触发

Kov*_*ovu 3 javascript web-component lit-element

我有以下代码:

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

 onChange(e) { console.log(e.target.value) }

 render()
{
    return html`
    <div>

        <div>
            <input id="vi-input" 
                type="text" 
                value="${this.value}"
                @change=${this.onChange} />
        </div>
    </div>
        `
}
Run Code Online (Sandbox Code Playgroud)

所以一切都运转良好。现在使用我的组件的开发人员应该能够通过属性设置值,例如

  document.getElementById('myComponent').value = 1;
Run Code Online (Sandbox Code Playgroud)

现在这带来了两个问题:1)值本身没有更新,2)onchange 没有被触发

问题1我通过改变解决了

value="${this.value}"
Run Code Online (Sandbox Code Playgroud)

到

.value="${this.value}"
Run Code Online (Sandbox Code Playgroud)

即使我也不知道它为什么起作用(在网上找到了这个黑客)。

但 onChange 仍然没有触发......

Ala*_*los 6

由于以下几个原因,代码无法像您预期的那样工作:

  1. 为什么在value什么时候.value不起作用?

lit-html这里用点号来区分赋值属性还是属性(value赋值属性和.value属性)

考虑这个问题的最简单方法是,属性是在 HTML 本身上设置的那些属性,而属性被设置为代表该节点的 Javascript 对象。

现在,这在这种情况下很重要,因为输入元素的 value 属性仅在第一次呈现时从属性设置,如果以后要更改它,则必须设置属性,而不是属性。来源

  1. 为什么从代码更改 value 属性时不触发更改事件?

这是因为仅当输入的值因某些用户输入而更改时,才会从输入触发更改事件。来源

如果您希望产生某种副作用,不仅在用户与输入交互时触发,而且在代码中修改属性时触发,您可能需要使用 setter。在您的情况下,它看起来像这样:

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

  set value(value) {
    const oldValue = this.value;
    // do some side effect here        
    // set a pseudo-private property that will contain the actual value
    this._value = value;
    // call LitElement's requestUpdate so that a rerender is done if needed
    this.requestUpdate('value', oldValue);
  }

  get value() {
    // return the pseudo-private so that when vitextfield.value is accessed the correct value is returned
    return this._value;
  }

  onChange(e) {
    // update the property so that it keeps up with the input's current value
    this.value = e.target.value;
  }

  render() {
    return html `
    <div>
        <div>
            <input id="vi-input" 
                type="text" 
                value="${this.value}"
                @change=${this.onChange} />
        </div>
    </div>
        `
  }
}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请查看LitElement 指南的这一部分