LitElement Web 组件表单事件目标设置为 null

LitElement web component form event target set to null

我有一个表单提交的事件处理程序,它在 HTTP 请求中发送数据,然后一旦收到响应,它就会重置表单。但是,似乎事件对象上的 target 属性 最初可用,但很快被设置为空。下面的示例是我尝试将问题提炼成一个最小的示例(为了帮助使其可重现,我使用 setTimeout 代替 HTTP 请求)。它显示虽然事件对象最初具有表单元素作为其目标 属性,但在等待一段时间后,目标 属性 被设置为 null。这会阻止我在 HTTP 请求完成后重置表单。

import { LitElement, css, html } from "lit-element";
import { render } from "lit-html";

class TestElement extends LitElement {
  submitForm(e) {
    e.preventDefault();
    console.log(e.target); // successfully logs <form> element
    window.setTimeout(() => {
      console.log(e); // logs event, with target now set to null
      e.target.reset(); // "Uncaught TypeError: Cannot read property 'reset' of null"
    }, 2000);
  }

  render() {
    return html`<form @submit=${this.submitForm}>
      <div class="form-controls">
        <label for="name">Name</label>
        <input type="text" id="name" name="name" />
        <label for="address">Address</label>
        <input type="text" id="address" name="address" />
        <button type="submit">submit</button>
      </div>
    </form>`;
  }
}
customElements.define("test-element", TestElement);
render(html`<test-element></test-element>`, window.document.body);

问题在于 webcomponent 事件是“重新定位”的,这意味着一旦事件从 webcomponent 中冒出进入光 DOM,事件的目标 属性 就会更新为 webcomponent本身。

为避免此问题,请不要使用 event.target 而是直接查询元素,例如使用 this.shadowRoot:

class TestElement extends LitElement {
  submitForm(e) {
    e.preventDefault();
    const form = this.shadowRoot.querySelector("form");
    console.log(e.target, form); // successfully logs <form> element
    window.setTimeout(() => {
      console.log(form); // successfully logs <form> element
      form.reset(); // resets form
    }, 2000);
  }

  render() {
    return html`<form @submit=${this.submitForm}>
      <div class="form-controls">
        <label for="name">Name</label>
        <input type="text" id="name" name="name" />
        <label for="address">Address</label>
        <input type="text" id="address" name="address" />
        <button type="submit">submit</button>
      </div>
    </form>`;
  }
}
customElements.define("test-element", TestElement);