Laravel开发JS报错Uncaught TypeError: 无法设置HTMLFormElement只读elements属性
报错根本原因
- 控制台抛出的
Uncaught TypeError: Cannot set property elements of #<HTMLFormElement> which has only a getter完全是由makeSerializable函数里的$(elem).prop('elements', ...)逻辑触发的。 - 按照现行Web标准,原生
HTMLFormElement对象自带的elements属性是仅支持读取的只读属性,不允许开发者手动覆盖赋值。早年部分浏览器对该属性的写入操作校验宽松,赋值会被静默忽略,所以旧代码能正常运行;现在主流浏览器严格遵循标准实现,一旦对该只读属性执行写入操作,会直接抛出类型错误,阻断后续所有JS执行流程。 - 这段旧代码本质是早年兼容
jquery.serializeJSON插件的hack写法:因为部分动态渲染的表单元素没有被原生form.elements集合收录,开发者尝试强行把表单内的所有DOM元素塞给elements属性,让序列化逻辑能遍历到所有字段,这个绕过标准的写法在现在的浏览器环境下已经完全失效。
对应修复方案
- 第一优先级:彻底移除给原生
elements属性赋值的错误逻辑,不要尝试修改DOM对象的只读属性。 - 适配序列化需求的改写方案:调整
makeSerializable函数的实现逻辑,不触碰原生DOM属性,直接返回包含所有可序列化字段的jQuery集合供后续serializeJSON调用:// 修复后的makeSerializable函数 function makeSerializable(elem) { // 收集目标表单本身 + 表单内所有带name属性的可序列化字段,直接返回jQuery集合 return $([$(elem).get()[0], ...$('[name]', elem).get()]); } - 业务逻辑的配套优化:
- 在收集图片文件的循环里增加判空校验,避免未选择图片时提交空值:
$(file_inputs).each(function(index, input) { // 仅当input存在选中文件时才追加到FormData if (input.files[0]) { data.append('image', input.files[0]); } }); - 两个独立业务JS都调用
makeSerializable的场景,把修复后的函数统一放到公共工具JS中维护,避免在各业务文件中残留旧的报错写法。 - 只要目标表单内的输入框都按规范设置了
name属性,其实可以省略makeSerializable的封装,直接对选中的表单元素调用.serializeJSON()即可,不需要额外的元素收集逻辑。
- 在收集图片文件的循环里增加判空校验,避免未选择图片时提交空值:
内容的提问来源于stack exchange,提问作者user15076625
相关产品推荐
相关产品推荐

