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);
我有一个表单提交的事件处理程序,它在 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);