先记住这个答案
脚本想让表单像用户按了提交按钮一样处理,应调用 form.requestSubmit()。它会检查 required、格式等约束;无效时阻止提交,有效时触发 submit 事件,事件处理器可再调用 preventDefault()。form.submit() 则直接启动提交,不触发 submit 事件,也不走通常的交互式约束校验。
requestSubmit()运行约束校验- 校验通过才触发
submit submit()绕过校验和事件- 传入按钮可采用其提交配置
搜索表单按快捷键提交
页面提供全局快捷键触发搜索,表单自身仍有必填关键词。用 requestSubmit() 可以复用同一条原生校验和 submit 事件逻辑,不必在快捷键代码里复制一遍校验。
<form id="search-form">
<input name="q" required>
<button type="submit">搜索</button>
</form>
<script>
const form = document.querySelector('#search-form')
document.addEventListener('keydown', event => {
if (event.key !== 'k' || !event.ctrlKey) return
event.preventDefault() // Ctrl+K 触发搜索,而不是浏览器默认动作
form.requestSubmit() // 空关键词会被原生校验拦下
})
</script>用户按下 Ctrl+K 后,若字段为空,浏览器阻止提交并提示用户;若填写有效,才继续触发 submit 事件。真实产品还要考虑 Mac 上的快捷键、输入法组合键和浏览器已有快捷键,不应无条件占用常见组合。
使用 form.submit() 可能绕过页面已有的 submit 监听器,导致埋点、确认提示或自定义数据处理完全不运行。
指定提交按钮会影响请求
表单有“保存草稿”和“正式发布”两个按钮时,传入对应按钮给 requestSubmit(button),可以采用该按钮的名称、值及 formaction 等覆盖属性。无参数时以表单自身作为提交者,不能假设会自动使用某个按钮。
传入的元素必须是属于该表单的提交按钮。普通按钮或别的表单里的按钮会抛异常;这比把任意元素都塞进去“试试看”更容易暴露逻辑错误。
requestSubmit(button) 还决定哪个按钮成为提交者。例如“保存草稿”按钮带 formnovalidate,而“发布”按钮没有:传入前者就会使用它的跳过校验设置,传入后者则照常校验。无参数调用不能假设浏览器替你选中了页面上某个按钮。若页面里某个控件的 name="submit" 覆盖了 form.submit 方法,使用 requestSubmit 也能避免直接调用旧方法时遇到的命名冲突;但最好还是不要把控件命名为 DOM 方法名。
容易答错的地方
- 认为
submit()会触发submit事件 - 直接调用方法不会触发通常的提交事件,也绕过原生交互式校验。
- 以为
requestSubmit()只是在派发事件 - 它先按提交流程做约束校验;校验失败时不会进入正常提交事件处理。
面试官还会怎么问?
如何阻止真正导航或发送请求?
在 submit 事件监听器中调用 event.preventDefault(),再执行自己的异步处理。
有两个提交按钮怎么区分?
传入实际提交按钮,事件中可通过 event.submitter 知道是哪一个。
传入普通 button 会怎样?
不是提交按钮会抛 TypeError;提交按钮不属于该表单也会报错。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。