[前端][fmui]避免跳转页面产生历史记录

问题现象:

在某些第三方容器中,标准的 window.location.replace() 方法可能无法正常工作或仍会产生历史记录。 [知识库地址1](问题信息表详情页面 (epoint.com.cn)open in new window)

通过直接修改 <iframe> 元素的 src 属性进行页面跳转时,会在浏览器历史记录中新增一条记录,导致用户可通过“返回”按钮回到前一页面。 [知识库地址2](问题信息表详情页面 (epoint.com.cn)open in new window)

问题原因:

  1. 三方容器环境差异
    • 部分容器对 location.replace 的实现与标准浏览器不一致,可能导致其行为等同于 location.href 赋值,从而新增历史记录。
    • 某些安全策略或权限限制可能阻止脚本直接操作浏览历史栈。
  2. iframe 默认导航行为
    • 直接设置 iframe.src 会触发浏览器的标准导航流程,该流程默认会新增历史记录。
    • 与顶级窗口不同,iframe 内部的历史记录操作需要在其 contentWindow 上下文中执行。

解决方案:

1. 三方容器不支持 location.replace 的解决方案

通过结合 history.replaceState() 与强制跳转,模拟 replace 效果:

// 第一步:修改当前 URL(不刷新页面)
history.replaceState(null, "", newURL);
// 第二步:强制重定向到新 URL
window.location.href = newURL;

2. 改变 iframe.src 产生历史记录的解决方案

2.1(同源) 通过 iframe 内部窗口的 location.replace() 方法进行跳转:

//改为使用location.replace来避免历史记录
iframe.contentWindow.location.replace(targetUrl);

2.2 (跨域/同源)动态创建销毁iframe

在需要跳转时,通过创建新的 iframe 元素替换旧的 iframe 元素,从 DOM 中移除旧的 iframe:

const container = document.getElementById('iframeContainer');
container.innerHTML = `<iframe src="${targetUrl}" width="100%" height="500px"></iframe>`;

2.3 (跨域)postMessage 通信

//在父页面中:

// 获取 iframe 元素
const iframe = document.getElementById('myIframe');
// 向 iframe 发送跳转指令
iframe.contentWindow.postMessage({
  type: 'redirect',
  url: targetUrl,
  method: 'replace' // 指定使用 replace 方法
}, '*'); // 第二个参数为目标源,生产环境应指定具体域名

//在 iframe 内部页面中:

// 监听父页面消息
window.addEventListener('message', function(event) {
  // 验证消息来源(生产环境应严格验证)
  if (event.data.type === 'redirect') {
    if (event.data.method === 'replace') {
      // 使用 replace 方法跳转,避免产生历史记录
      window.location.replace(event.data.url);
    } else {
      // 默认跳转方式
      window.location.href = event.data.url;
    }
  }
});
最后更新时间::
贡献者: wyanqd