target属性必须写在标签上,而非按钮或js中;正确用法是,formtarget可为多按钮指定不同跳转目标,iframe方案可绕过弹窗拦截。

target 属性必须写在 <form></form> 标签上,不是按钮也不是 JS
很多人把 target="_blank" 加到 <button type="submit"></button> 或 <input type="submit"> 上,或者试图在 JavaScript 里用 location.href 模拟跳转——结果表单照样刷新当前页。因为浏览器只认 <form></form> 元素自身的 target 属性,它和 action、method 是同级的 HTML 属性。
正确写法是:
-
target写在<form></form>外层才生效;写在子元素上会被忽略 - JS 中可以通过
formElement.target = "_blank"动态设置,但前提是操作对象是<form></form>DOM 节点本身 - 如果用了 Vue/React 等框架并调用了
event.preventDefault(),那target完全不触发——它只对原生表单提交起作用
为什么 target="_blank" 经常没反应
不是代码写错了,而是现代浏览器(尤其是 Chrome、Safari)会拦截“非用户主动触发”的新窗口。表单提交虽由点击发起,但若满足以下任一条件,target="_blank" 就可能静默失败:
- 页面刚加载完就自动
form.submit()(无真实点击) - 提交逻辑藏在 Promise 回调或 setTimeout 里(失去用户手势上下文)
- 启用了严格 CSP 策略,比如
popup-src 'none' - 控制台报
Failed to open window或类似错误
验证方法:打开 DevTools → Console,手动执行 document.querySelector('form').submit(),看是否弹窗;如果不行,说明环境已拦截。
用隐藏 <iframe></iframe> 替代 _blank 更可靠
这是绕过弹窗拦截最稳的方案:让表单响应渲染进一个 display:none 的 <iframe></iframe>,再监听它的 load 事件做后续处理。
关键点:
-
<form target="myframe"></form>中的myframe必须和<iframe name="myframe"></iframe>的name完全一致 -
<iframe></iframe>可设style="display:none",但不能用hidden属性(部分浏览器不触发load) - 服务端返回纯 HTML 响应即可,前端无需改提交方式
- 监听 iframe load 后可读取
iframe.contentDocument.body.innerHTML提取结果(注意同源限制)
formtarget 适合多按钮不同跳转场景
当一个表单有多个提交按钮,且希望各自导向不同目标时,formtarget 是唯一干净解法。它只作用于 type="submit" 的 <button></button> 或 <input>,优先级高于 <form></form> 的 target。
示例:
-
formtarget是 HTML5 新增属性,IE10+ 和所有现代浏览器都支持 - 它不适用于
type="button",也不影响 fetch/axios 等 JS 提交 - SPA 场景中,如果仍用原生提交(比如文件下载),
formtarget是比 JS 拼接window.open更轻量的选择
真正容易被忽略的是:_parent 和 _top 在现代页面里基本等价于 _self,除非你明确在嵌套 <iframe></iframe> 中运行——它们的设计初衷是配合已淘汰的 <frameset></frameset>,现在只剩 iframe 场景还有实际意义。











