name属性是决定字段是否被FormData采集的唯一开关,无name的控件(含文件输入)不会进入FormData;同名字段用get()仅获首值,getAll()才得全部;radio/checkbox未选中则完全不提交。

name属性是唯一决定字段是否被采集的开关
FormData只认name,不认id、class或自定义属性。没有name的控件(哪怕写了value)完全不会出现在FormData里。
常见错误现象:<input type="text" id="username">提交后formData.get("username")返回undefined——因为没设name。
- 必须显式写
name="username",且值不能为空字符串(name=""等同于无name) -
name含空格、点号、方括号(如user.profile.name或items[0].title)是合法的,但只是字符串键名,不会自动解析为嵌套结构 - 多个同名控件(如多选
<input type="checkbox" name="tag">)会按顺序append,调用getAll("tag")才能拿到全部值
radio和checkbox未选中时根本不会进FormData
这是HTML规范行为,不是bug。只有checked === true的<input type="radio">或<input type="checkbox">才会被收集。
典型陷阱:表单里一组name="gender"的radio,用户一个都没选,formData.has("gender")返回false,后端收不到这个字段。
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
- 如果业务要求“未选中也要传默认值”,得手动补:
if (!formData.has("gender")) formData.append("gender", "unknown") - 更轻量的做法是后端约定“字段缺失即为未选择”,前端不干预——避免前后端对空值语义的理解错位
- 别用
form.elements["gender"]遍历再判断checked,直接查formData.has("gender")更可靠
name重复时append顺序影响get()结果
get("key")永远只返回第一个值,getAll("key")才返回所有。这在动态追加或重置字段时容易出错。
比如先有<input name="hobby" value="篮球">,再用formData.append("hobby", "足球"),formData.get("hobby")仍是“篮球”,formData.getAll("hobby")才是["篮球", "足球"]。
- 想覆盖旧值用
set("key", "new"),它会清空同名所有项再设新值 - 想确保只有一份值,提交前检查:
if (formData.getAll("hobby").length > 1),再决定取第一个还是合并 - 服务器端接收多值字段时,注意框架默认行为(如Express的
req.body.hobby可能是字符串或数组,取决于中间件配置)
带文件的表单必须用FormData,且name不能省略
文件控件<input type="file" name="avatar">的name决定了后端接收到的字段名,也决定了FormData里该条目的key。漏掉name,文件就丢了。
错误示例:<input type="file" id="avatar"> → formData.get("avatar")是undefined,且formData.entries()里根本找不到它。
- 文件字段的value是
File或FileList对象,不是字符串,toString()没意义 - 多个文件用
<input type="file" name="photos" multiple>,formData.getAll("photos")会返回[File, File]数组 - 不要试图把File转成base64再塞进普通表单字段——破坏二进制完整性,增大传输体积,且失去
multipart/form-data的流式上传优势
name属性在混合场景下的隐式依赖:比如用JS动态生成表单项却忘了赋name,或者服务端解析逻辑硬编码了字段层级而前端只传了扁平name。这种错不在语法,而在映射契约的断裂。

















