FormData、新的 formdata 事件和 HTML 表单
你听说过新的formdata事件吗?它只是一个新的DOM事件,但Web平台的每一个新功能都让我感到兴奋。
什么是 FormData?
在深入探讨细节之前,我们先来明确一下FormData 是什么。对于 Web 开发新手来说,HTML 表单能够触发事件。这几乎是所有 HTML 元素都具备的特性。
考虑以下形式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML forms and JavaScript</title>
</head>
<body>
<form>
<label for="name">Name</label>
<input type="text" id="name" name="name" required>
<label for="description">Short description</label>
<input type="text" id="description" name="description" required>
<label for="task">Task</label>
<textarea id="task" name="task" required></textarea>
<button type="submit">Submit</button>
</form>
</body>
<script src="form.js"></script>
</html>
为了方便您操作,您可以创建一个 HTML 文件,并复制我的示例。当表单提交时(即用户填写完字段并点击“提交”按钮后),会触发一个名为submit 的事件。
这意味着我们可以使用事件监听器来监听提交事件:
// form.js
const form = document.forms[0];
form.addEventListener("submit", function(event) {
event.preventDefault();
});
调用 preventDefault() 可以防止页面刷新,当您不想在后端发送表单字段时,这很方便。
现在,有两种方法可以从表单中获取实际数据。您可以检查event.target.elements,在本例中,它会返回所有表单元素。
或者更好的是,您可以使用FormData(一个 DOM 接口)作为构造函数。它需要表单作为参数:
const form = document.forms[0];
form.addEventListener("submit", function(event) {
event.preventDefault();
const data = new FormData(form);
});
从现在开始,你可以对 FormData 对象执行各种操作。稍后会详细介绍。现在让我们来探索 formdata 事件。
了解 formdata 事件
formdata事件是 Web 平台新增的一项实用功能。作为 FormData 的增强功能,每当您调用 new FormData() 时,都会触发此事件。现在请看以下示例:
const form = document.forms[0];
form.addEventListener("submit", function(event) {
event.preventDefault();
new FormData(form);
});
form.addEventListener("formdata", event => {
// event.formData grabs the object
console.log(event.formData);
});
在第一个事件监听器中,我们从表单构建一个新的 FormData 对象。这次无需将结果保存到变量中。
响应此调用,新对象会触发 formdata 事件,我们在该事件上注册另一个监听器。
在第二个监听器中,我们可以从 event.formData 中获取实际数据。
这种模式有助于将第一个事件监听器与任何其他应该处理实际表单数据(进行 API 调用等)的回调函数解耦。
下一节我们将学习如何从 FormData 对象中获取数据。
从 FormData 对象中获取数据
如果你想窥探 FormData 对象,请在浏览器中访问示例 HTML 表单,并在console.log(event.formData)处设置断点。
打开浏览器控制台,填写并提交表单,并将对象保存为全局变量:
您应该能够在 Chrome 浏览器中访问该对象 (temp1):
console.log(temp1)
// FormData {append: ƒ, delete: ƒ, get: ƒ, getAll: ƒ, has: ƒ, …}
如您所见,它有很多方法。要提取值数组,请运行:
const values = [...temp1.values()]
// sample output
// ["Liz", "Trip to London", "Trip to London"]
要提取条目数组,请运行:
const entries = [...temp1.entries()]
在我们的示例中,我们可以从 FormData 对象中获取各种形状的所有数据:
const form = document.forms[0];
form.addEventListener("submit", function(event) {
event.preventDefault();
new FormData(form);
});
form.addEventListener("formdata", event => {
const data = event.formData;
// get the data
const entries = [...data.entries()];
console.log(entries);
const values = [...data.values()];
console.log(values);
});
需要注意的是:FormData 依赖表单字段的名称属性来构建字段和值之间的映射关系。这意味着以下元素不会产生任何结果:
<!-- bad -->
<input type="text" id="name" required>
<input type="text" id="description" required>
务必为字段命名:
<!-- good -->
<input type="text" id="name" name="name" required>
<input type="text" id="description" name="description" required>
向 FormData 对象添加数据
在HTML表单中设置隐藏输入框,以便在提交阶段保存额外数据,是一种常见的做法:
<!-- no more hidden fields -->
<input type="hidden" id="someInfo" name="someSecretInfo" value="someSecreteInfo">
隐藏的输入框不会显示在渲染后的 HTML 中(但仍然可以通过开发者控制台访问)。
除了从 FormData 对象中读取表单字段外,还可以使用 append添加新的键/值对:
// omitted for brevity
form.addEventListener("formdata", event => {
const data = event.formData;
// append more fields
data.append("anHiddenKeyA", "anHiddenValueA");
data.append("anHiddenKeyB", "anHiddenValueB");
// get the data
const entries = [...data.entries()];
console.log(entries);
const values = [...data.values()];
console.log(values);
});
这样可以方便地避免在 HTML 表单中使用隐藏的输入字段。
由于formdata 事件是平台的新增功能,因此在旧版浏览器中不可用,请谨慎使用。
感谢阅读,敬请期待更多精彩内容!
