重新加载 IFRAME 而不添加到历史记录

Posted

技术标签:

【中文标题】重新加载 IFRAME 而不添加到历史记录【英文标题】:Reload an IFRAME without adding to the history 【发布时间】:2010-10-23 17:02:19 【问题描述】:

我正在更改 IFRAME 的 src 以重新加载它,它工作正常并在其 html 加载时触发 onload 事件。

但它在历史记录中添加了一个条目,这是我不想要的。有什么方法可以重新加载 IFRAME 而又不影响历史记录?

【问题讨论】:

我猜问题是后退按钮在实际转到上一页之前实际上会在 iframe 中循环。 不管它做什么,我都不想添加任何历史记录,或者有什么方法可以删除最新的历史记录?? 【参考方案1】:

你可以使用javascriptlocation.replace:

window.location.replace('...html');

将当前文档替换为 一个在提供的 URL。这 与 assign() 方法的区别是 使用 replace() 后,当前 页面不会保存在会话中 历史,这意味着用户不会 能够使用返回按钮 导航到它。

【讨论】:

这不是针对页面本身吗?我只想重新加载 IFRAME,我无法控制在加载的文档中运行的脚本。 只需将“window”替换为对您的 iframe 的引用即可。 为什么没那么简单? var ifr = document.getElementById("iframeId"); ifr.location.replace(ifr.src); 尝试使用window.frames['frame_name'].location 你也可以使用iframe.contentWindow.location.replace(href);【参考方案2】:

就像 Greg 上面所说的, .replace() 函数就是如何做到这一点的。我似乎不知道如何回复他的答案*,但诀窍是引用 iFrames contentWindow 属性。

var ifr = document.getElementById("iframeId");
ifr.contentWindow.location.replace("newLocation.html"); 

*刚刚得知我需要更多声望才能对答案发表评论。

【讨论】:

【参考方案3】:

使用 replace() 只是您自己的域 iframe 的一个选项。它无法在远程站点上工作(例如:twitter 按钮),并且需要一些特定于浏览器的知识才能可靠地访问子窗口。

相反,只需删除 iframe 元素并在同一位置构建一个新元素。只有在 src 属性在 DOM 中之后修改它时才会创建历史记录项,因此请确保在追加之前设置它。

编辑:JDandChips 正确地提到您可以从 DOM 中删除、修改和重新附加。不需要构建新鲜的。

【讨论】:

虽然这个答案比公认的答案更新了 2 年,但它是在不添加浏览器历史记录的情况下更改 iframe URL/src 的正确方法。出于安全原因,window.frames[frameName].location 和/或 history.replaceState 的任何其他组合都不能在 iframe 中使用。即使在同一个域上(正如我刚刚发现的那样)。 这是我尝试过的最佳工作答案。解决了我的问题。 解决方案就是这个!我需要创建 iframe,以便历史记录保持不变。 很好的答案。我试图添加带有 iframe 和 Angular 的 vimeo 嵌入视频,如下所示:<div ng-repeat="item in ct.items"><iframe src="item.url"></iframe></div>。碰巧在 angular 设置 iframe url 之前,html 尝试使用错误的 url 加载 iframe,例如 item.url,结果是 iframe 的 src 更改了,导致浏览器历史记录问题!解决方案是稍后使用 jquery 创建 iframe,在 angular 渲染完所有内容之后。 如果从 iframe 本身内部更改 url 是否也会出现此问题(例如,如果用户单击或 J.S. 重定向到 iframe 内的第二页)?我不直接通过 DOM 更改 iframe src。例如:我的 SPA 中的 iframe 中嵌入了一个 Adob​​eEsign 页面,该页面重定向到同一 iframe 中的感谢页面(然后感谢页面将 windows.postmessage 发送回我的主框架,以便我可以关闭 iframe)。 ..但此时单击我的 SPA 中的浏览器后退按钮似乎想要“离开页面”(我的 window.beforeunload 事件在用户离开 SPA 时触发)。【参考方案4】:

尝试使用此功能将旧 iframe 替换为从旧 iframe 复制的新 iframe:

function setIFrameSrc(idFrame, url) 
    var originalFrame = document.getElementById(idFrame);
    var newFrame = document.createElement("iframe");
    newFrame.id = originalFrame.getAttribute("id");
    newFrame.width = originalFrame.getAttribute("width");
    newFrame.height = originalFrame.getAttribute("height");
    newFrame.src = url;    
    var parent = originalFrame.parentNode;
    parent.replaceChild(newFrame, originalFrame);

像这样使用它:

setIFrameSrc("idframe", "test.html");

这种方式不会将 iframe 的 URL 添加到浏览器历史记录中。

【讨论】:

这很方便。谢谢!【参考方案5】:

另一种重新创建 iframe 的方法是从 DOM 中删除 iframe,更改 src 然后重新添加它。

在很多方面,这类似于 replace() 的建议,但是当我尝试使用 History.js 并手动管理状态时遇到了一些问题。

var container = iframe.parent();

iframe.remove();
iframe.attr('src', 'about:blank');

container.append(iframe);

【讨论】:

我真的很喜欢这个:结果证明它比创建一个新的 iframe 要容易得多,因为您不需要将所有属性复制到新的 iframe(id、大小、样式类、. ..) 很棒的发现。在 Bootstrap 模式窗口中加载 iframe 内容的情况下,此解决方案对我有用。当模态框关闭时,使用回调将其删除,然后将其添加回来。修复后退按钮问题。 $(modal).one('hidden.bs.modal', function() $(modal_iframe).attr('src', 'about:blank').addClass('d-none'); var modalParent = $(modal_iframe).parent(); $(modal_iframe).remove(); $(modalParent).append($(modal_iframe)); );【参考方案6】:

一种解决方案是使用object 标签而不是iframe 标签。

替换这个:

<iframe src="http://yourpage"/>

通过这个:

<object type="text/html" data="http://yourpage"/>

将允许您在不影响历史记录的情况下更新data 属性。如果您使用诸如 React.js 之类的声明性框架,您不应该执行任何命令式命令来更新 DOM,这将非常有用。

有关iframeobject 之间差异的更多详细信息:Use of Iframe or Object tag to embed web pages in another

【讨论】:

同意@JBE 的好答案,这对我使用 Angular2 有很大帮助,并且没有 iframe src 更改触发历史更新。 这对我不起作用。我在 Chrome 中。即使销毁 iframe 并用对象替换它仍然会导致该死的浏览器历史状态(这是没有意义的,因为被销毁的对象永远不会取回它的内容)。 Grrrrrrrrrr。【参考方案7】:

最简单快速的加载方案 加载页面或框架时使用window.location.replace 不更新历史记录。

对于链接,它看起来像这样:

<a href="#" onclick="YourTarget.location.replace ('http://www.YourPage.com');">
The targeted Link</a>

<a href="javascript:YourTarget.location.replace ('http://www.YourPage.com');">
The targeted Link</a>

但是如果您不希望它从链接执行,而是在加载框架时自动执行,那么您应该从 iframe 将其放入 iframe 文件正文部分:

onload="window.location.replace ('http://www.YourPage.com');"

如果由于某种原因 onload 未在 iframe 中加载,则将目标框架名称而不是 window 放在如下语法中:

onload="YourTarget.location.replace ('http://www.YourPage.com');"

注意:对于此脚本,所有 onclickonmouseoveronmouseoutonloadhref="javascript:" 都可以使用。

【讨论】:

【参考方案8】:

使用replace 方法绕过将 iframe 的 URL 添加到历史记录:

HTML:

<iframe id="myIframe"   src="#"></iframe>

JavaScript:

var ifr = document.getElementById('mIframe')
if (ifr) 
  ifr.contentWindow.location.replace('http://www.blabla.com')

【讨论】:

【参考方案9】:

JDandChips 答案在跨源 iframe (youtube) 上为我工作,这里是 vanilla JS(没有 JQuery):

const container = iframe.parentElement;

container.removeChild(iframe);

iframe.setAttribute('src', 'about:blank');

container.appendChild(iframe);

【讨论】:

【参考方案10】:

@JDandChips 上面有一个很好的答案,但是语法应该从 parent() 更新为 parentElement

var container = iframe.parentElement;

iframe.remove();
iframe.attr('src', 'about:blank');

container.append(iframe);

【讨论】:

欢迎来到 ***!如果答案基本上是正确的,并且真的只需要小幅更新,您应该suggest an edit 回复答案,而不是自己发布一个新答案。如果您的建议被接受,它会给您一个badge :)

以上是关于重新加载 IFRAME 而不添加到历史记录的主要内容,如果未能解决你的问题,请参考以下文章

使用 Ionic 框架在登录/注销时清除历史记录并重新加载页面

撤消已发布的合并并重新应用原始更改而不重写历史记录

禁止iframe页面时产生历史记录

SVN 转储/重新加载具有历史记录的特定版本

如何在 iframe 之外操作历史记录

继续在历史记录中前后添加行