您现在的位置是:网站首页 > 表单的目标窗口(target)文章详情

表单的目标窗口(target)

表单的目标窗口(target)

表单的target属性决定了表单提交后服务器返回的响应内容在哪个窗口或框架中显示。这个看似简单的属性在实际开发中能实现多种特殊交互效果,特别是在多窗口/框架场景下。

target属性的基础用法

target属性可以设置在<form>标签上,也可以单独设置在<input type="submit"><button type="submit">上。当两者同时存在时,按钮级别的设置会覆盖表单级别的设置。

<!-- 表单级target设置 -->
<form action="/submit" target="_blank">
  <input type="text" name="username">
  <input type="submit" value="提交">
</form>

<!-- 按钮级target设置 -->
<form action="/submit">
  <input type="text" name="email">
  <button type="submit" target="_self">提交</button>
</form>

预定义的target值

HTML规范定义了四个特殊的target值,它们都以下划线开头:

  1. _blank:在新窗口/标签页打开

    <form action="/search" target="_blank">
      <input type="search" name="q">
      <button type="submit">搜索</button>
    </form>
    
  2. _self:在当前窗口打开(默认值)

    <!-- 效果相同 -->
    <form action="/login" target="_self"></form>
    <form action="/login"></form>
    
  3. _parent:在父框架集中打开

    <!-- 框架集示例 -->
    <frameset rows="50%,50%">
      <frame src="top.html" name="topFrame">
      <frame src="form.html" name="formFrame">
    </frameset>
    
    <!-- form.html内容 -->
    <form action="/update" target="_parent">
      <!-- 表单内容 -->
    </form>
    
  4. _top:在整个窗口打开,取消所有框架

    <!-- 多层框架中 -->
    <form action="/exit" target="_top">
      <!-- 点击提交后将跳出所有框架 -->
    </form>
    

命名窗口与框架的target

除了预定义值,target还可以指定具体的窗口或框架名称:

<!-- 命名窗口示例 -->
<a href="/help" target="helpWindow">帮助</a>

<form action="/chat" target="helpWindow">
  <input type="text" name="message">
  <input type="submit" value="发送">
</form>

<script>
// 点击链接时确保窗口存在
document.querySelector('a').addEventListener('click', function() {
  if (!window.open('', 'helpWindow')) {
    window.open('/help', 'helpWindow', 'width=400,height=600');
  }
});
</script>

框架集场景下的命名target:

<frameset cols="30%,70%">
  <frame src="nav.html" name="nav">
  <frame src="main.html" name="main">
</frameset>

<!-- nav.html中的表单 -->
<form action="/load" target="main">
  <select name="page">
    <option value="home">首页</option>
    <option value="products">产品</option>
  </select>
  <input type="submit" value="加载">
</form>

动态修改target

通过JavaScript可以动态修改表单的target属性,实现更灵活的交互:

<form id="dynamicForm" action="/process">
  <input type="text" name="data">
  <button type="submit" id="newTabBtn">新标签页提交</button>
  <button type="submit" id="sameTabBtn">当前页提交</button>
</form>

<script>
document.getElementById('newTabBtn').addEventListener('click', function() {
  document.getElementById('dynamicForm').target = '_blank';
});

document.getElementById('sameTabBtn').addEventListener('click', function() {
  document.getElementById('dynamicForm').target = '_self';
});
</script>

iframe作为target的应用

iframe可以作为表单提交的目标,实现无刷新提交:

<iframe name="hiddenFrame" style="display:none;"></iframe>
<form action="/upload" target="hiddenFrame" enctype="multipart/form-data">
  <input type="file" name="file">
  <input type="submit" value="上传">
</form>

<script>
window.frames['hiddenFrame'].onload = function() {
  // 获取iframe中的响应
  const response = this.document.body.innerHTML;
  console.log('上传结果:', response);
};
</script>

多表单共享target

多个表单可以共享同一个目标窗口,这在某些管理后台中很有用:

<!-- 控制台主界面 -->
<div id="console"></div>

<!-- 多个工具表单 -->
<form action="/tool1" target="consoleOutput">
  <!-- 表单内容 -->
</form>

<form action="/tool2" target="consoleOutput">
  <!-- 表单内容 -->
</form>

<iframe name="consoleOutput" onload="
  document.getElementById('console').innerHTML = 
    this.contentDocument.body.innerHTML;
"></iframe>

target与window.open的配合

结合window.open可以精确控制新窗口的特性:

<form id="popupForm" action="/preview">
  <textarea name="content"></textarea>
  <button type="submit">预览</button>
</form>

<script>
document.getElementById('popupForm').addEventListener('submit', function(e) {
  const previewWin = window.open('', 'previewWindow', 
    'width=600,height=400,resizable=yes');
  this.target = 'previewWindow';
  if (!previewWin || previewWin.closed) {
    this.target = '_blank';
  }
});
</script>

安全限制与注意事项

现代浏览器对target行为有一些安全限制:

  1. 同源策略:目标窗口必须同源才能通过JavaScript访问其内容
  2. 弹出窗口拦截:某些浏览器设置会阻止_blank的窗口打开
  3. 框架限制:X-Frame-Options头可能阻止框架加载
<!-- 检测target是否生效的示例 -->
<form action="/test" target="testFrame" onsubmit="
  return checkTarget('testFrame')">
  <!-- 表单内容 -->
</form>

<script>
function checkTarget(targetName) {
  try {
    const win = window.open('', targetName);
    if (!win) {
      alert('请允许弹出窗口');
      return false;
    }
    win.close();
    return true;
  } catch (e) {
    console.error('Target检查失败:', e);
    return false;
  }
}
</script>

现代替代方案

虽然target仍然有效,但现代开发中常使用其他技术替代:

<!-- 使用Fetch API替代表单提交 -->
<form id="ajaxForm">
  <input type="text" name="query">
  <button type="submit">搜索</button>
</form>

<div id="result"></div>

<script>
document.getElementById('ajaxForm').addEventListener('submit', async function(e) {
  e.preventDefault();
  const formData = new FormData(this);
  const response = await fetch('/search', {
    method: 'POST',
    body: formData
  });
  document.getElementById('result').innerHTML = await response.text();
});
</script>

特殊场景下的应用技巧

  1. 多步骤表单:在不同阶段使用不同target

    <form id="multiStepForm">
      <!-- 第一步在当前页验证 -->
      <div class="step" data-step="1">
        <input type="text" name="email" required>
        <button type="button" onclick="nextStep(2)">下一步</button>
      </div>
      
      <!-- 第二步在新窗口确认 -->
      <div class="step" data-step="2" style="display:none;">
        <input type="text" name="code">
        <button type="submit" target="_blank">最终提交</button>
      </div>
    </form>
    
    <script>
    function nextStep(step) {
      document.querySelector('[data-step="1"]').style.display = 'none';
      document.querySelector('[data-step="2"]').style.display = 'block';
      document.getElementById('multiStepForm').action = '/verify';
    }
    </script>
    
  2. 下载文件:强制在新窗口下载

    <form action="/export" target="downloadFrame">
      <select name="format">
        <option value="csv">CSV</option>
        <option value="pdf">PDF</option>
      </select>
      <button type="submit">导出</button>
    </form>
    <iframe name="downloadFrame" style="display:none;"></iframe>
    

浏览器兼容性考虑

不同浏览器对target的处理有细微差异:

  • 旧版IE可能重复使用已关闭窗口的名称
  • 移动设备上_blank可能在新标签页而非新窗口打开
  • 某些浏览器会忽略框架窗口的target指定
<!-- 兼容性处理示例 -->
<form action="/submit" id="compatForm">
  <!-- 表单内容 -->
</form>

<script>
document.getElementById('compatForm').addEventListener('submit', function() {
  if (navigator.userAgent.indexOf('MSIE') > -1) {
    // IE特殊处理
    const newWin = window.open('', 'legacyTarget');
    if (newWin) this.target = 'legacyTarget';
  }
});
</script>

与CSS框架的配合

在使用Bootstrap等CSS框架时,target需要特殊处理:

<!-- Bootstrap模态框作为target -->
<div class="modal fade" id="resultModal" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-body" id="modalResult"></div>
    </div>
  </div>
</div>

<form action="/process" target="modalTarget">
  <!-- 表单内容 -->
</form>

<iframe name="modalTarget" style="display:none;" 
  onload="document.getElementById('modalResult').innerHTML = 
          this.contentDocument.body.innerHTML;
          $('#resultModal').modal('show');">
</iframe>

性能优化建议

大量使用target可能影响性能:

  1. 避免创建过多隐藏iframe作为target
  2. 及时清理不再使用的命名窗口
  3. 对于AJAX场景优先使用Fetch API
<!-- 优化示例:复用iframe -->
<script>
let targetIframe = null;

function getTargetIframe() {
  if (!targetIframe || targetIframe.parentNode === null) {
    targetIframe = document.createElement('iframe');
    targetIframe.name = 'reusableTarget';
    targetIframe.style.display = 'none';
    document.body.appendChild(targetIframe);
  }
  return targetIframe.name;
}

document.querySelector('form').target = getTargetIframe();
</script>

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步